Line data Source code
1 : /* $OpenBSD: clock_subr.c,v 1.6 2016/08/26 07:09:56 guenther Exp $ */
2 : /* $NetBSD: clock_subr.c,v 1.3 1997/03/15 18:11:16 is Exp $ */
3 :
4 : /*
5 : * Copyright (c) 1988 University of Utah.
6 : * Copyright (c) 1982, 1990, 1993
7 : * The Regents of the University of California. All rights reserved.
8 : *
9 : * This code is derived from software contributed to Berkeley by
10 : * the Systems Programming Group of the University of Utah Computer
11 : * Science Department.
12 : *
13 : * Redistribution and use in source and binary forms, with or without
14 : * modification, are permitted provided that the following conditions
15 : * are met:
16 : * 1. Redistributions of source code must retain the above copyright
17 : * notice, this list of conditions and the following disclaimer.
18 : * 2. Redistributions in binary form must reproduce the above copyright
19 : * notice, this list of conditions and the following disclaimer in the
20 : * documentation and/or other materials provided with the distribution.
21 : * 3. Neither the name of the University nor the names of its contributors
22 : * may be used to endorse or promote products derived from this software
23 : * without specific prior written permission.
24 : *
25 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 : * SUCH DAMAGE.
36 : *
37 : * from: Utah $Hdr: clock.c 1.18 91/01/21$
38 : *
39 : * @(#)clock.c 8.2 (Berkeley) 1/12/94
40 : */
41 :
42 : /*
43 : * Generic routines to convert between a POSIX date
44 : * (seconds since 1/1/1970) and yr/mo/day/hr/min/sec
45 : * Derived from arch/hp300/hp300/clock.c
46 : */
47 :
48 : #include <sys/types.h>
49 : #include <sys/time.h>
50 : #include <sys/systm.h>
51 :
52 : static inline int leapyear(int year);
53 : #define FEBRUARY 2
54 : #define days_in_year(a) (leapyear(a) ? 366 : 365)
55 : #define days_in_month(a) (month_days[(a) - 1])
56 :
57 : static const int month_days[12] = {
58 : 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
59 : };
60 :
61 : /*
62 : * This inline avoids some unnecessary modulo operations
63 : * as compared with the usual macro:
64 : * ( ((year % 4) == 0 &&
65 : * (year % 100) != 0) ||
66 : * ((year % 400) == 0) )
67 : * It is otherwise equivalent.
68 : */
69 : static inline int
70 0 : leapyear(int year)
71 : {
72 : int rv = 0;
73 :
74 0 : if ((year & 3) == 0) {
75 : rv = 1;
76 0 : if ((year % 100) == 0) {
77 : rv = 0;
78 0 : if ((year % 400) == 0)
79 : rv = 1;
80 0 : }
81 : }
82 0 : return (rv);
83 : }
84 :
85 : time_t
86 0 : clock_ymdhms_to_secs(struct clock_ymdhms *dt)
87 : {
88 : time_t secs;
89 : int i, year, days;
90 :
91 0 : year = dt->dt_year;
92 :
93 : /*
94 : * Compute days since start of time.
95 : * First from years, then from months.
96 : */
97 : days = 0;
98 0 : for (i = POSIX_BASE_YEAR; i < year; i++)
99 0 : days += days_in_year(i);
100 0 : if (leapyear(year) && dt->dt_mon > FEBRUARY)
101 0 : days++;
102 :
103 : /* Months */
104 0 : for (i = 1; i < dt->dt_mon; i++)
105 0 : days += days_in_month(i);
106 0 : days += (dt->dt_day - 1);
107 :
108 : /* Add hours, minutes, seconds. */
109 0 : secs = (time_t)((days
110 0 : * 24 + dt->dt_hour)
111 0 : * 60 + dt->dt_min)
112 0 : * 60 + dt->dt_sec;
113 :
114 0 : return (secs);
115 : }
116 :
117 : /* This function uses a copy of month_days[] */
118 : #undef days_in_month
119 : #define days_in_month(a) (mthdays[(a) - 1])
120 :
121 : void
122 0 : clock_secs_to_ymdhms(time_t secs, struct clock_ymdhms *dt)
123 : {
124 0 : int mthdays[12];
125 : int i, days;
126 : int rsec; /* remainder seconds */
127 :
128 0 : memcpy(mthdays, month_days, sizeof(mthdays));
129 :
130 0 : days = secs / SECDAY;
131 0 : rsec = secs % SECDAY;
132 :
133 : /* Day of week (Note: 1/1/1970 was a Thursday) */
134 0 : dt->dt_wday = (days + 4) % 7;
135 :
136 : /* Subtract out whole years, counting them in i. */
137 0 : for (i = POSIX_BASE_YEAR; days >= days_in_year(i); i++)
138 0 : days -= days_in_year(i);
139 0 : dt->dt_year = i;
140 :
141 : /* Subtract out whole months, counting them in i. */
142 0 : if (leapyear(i))
143 0 : days_in_month(FEBRUARY) = 29;
144 0 : for (i = 1; days >= days_in_month(i); i++)
145 0 : days -= days_in_month(i);
146 0 : dt->dt_mon = i;
147 :
148 : /* Days are what is left over (+1) from all that. */
149 0 : dt->dt_day = days + 1;
150 :
151 : /* Hours, minutes, seconds are easy */
152 0 : dt->dt_hour = rsec / 3600;
153 0 : rsec = rsec % 3600;
154 0 : dt->dt_min = rsec / 60;
155 0 : rsec = rsec % 60;
156 0 : dt->dt_sec = rsec;
157 0 : }
|