2 * Copyright (c) 2008 Christos Zoulas
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
15 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
30 FILE_RCSID("@(#)$File: cdf_time.c,v 1.15 2014/05/14 23:15:42 christos Exp $")
41 #define isleap(y) ((((y) % 4) == 0) && \
42 ((((y) % 100) != 0) || (((y) % 400) == 0)))
44 static const int mdays
[] = {
45 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
49 * Return the number of days between jan 01 1601 and jan 01 of year.
57 for (y
= CDF_BASE_YEAR
; y
< year
; y
++)
58 days
+= isleap(y
) + 365;
64 * Return the day within the month
67 cdf_getday(int year
, int days
)
71 for (m
= 0; m
< sizeof(mdays
) / sizeof(mdays
[0]); m
++) {
72 int sub
= mdays
[m
] + (m
== 1 && isleap(year
));
81 * Return the 0...11 month number.
84 cdf_getmonth(int year
, int days
)
88 for (m
= 0; m
< sizeof(mdays
) / sizeof(mdays
[0]); m
++) {
90 if (m
== 1 && isleap(year
))
99 cdf_timestamp_to_timespec(struct timespec
*ts
, cdf_timestamp_t t
)
102 #ifdef HAVE_STRUCT_TM_TM_ZONE
103 static char UTC
[] = "UTC";
107 /* Unit is 100's of nanoseconds */
108 ts
->tv_nsec
= (t
% CDF_TIME_PREC
) * 100;
111 tm
.tm_sec
= (int)(t
% 60);
114 tm
.tm_min
= (int)(t
% 60);
117 tm
.tm_hour
= (int)(t
% 24);
121 tm
.tm_year
= (int)(CDF_BASE_YEAR
+ (t
/ 365));
123 rdays
= cdf_getdays(tm
.tm_year
);
125 tm
.tm_mday
= cdf_getday(tm
.tm_year
, (int)t
);
126 tm
.tm_mon
= cdf_getmonth(tm
.tm_year
, (int)t
);
130 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
133 #ifdef HAVE_STRUCT_TM_TM_ZONE
137 ts
->tv_sec
= mktime(&tm
);
138 if (ts
->tv_sec
== -1) {
147 cdf_timespec_to_timestamp(cdf_timestamp_t
*t
, const struct timespec
*ts
)
155 if (gmtime_r(&ts
->ts_sec
, &tm
) == NULL
) {
159 *t
= (ts
->ts_nsec
/ 100) * CDF_TIME_PREC
;
161 *t
+= tm
.tm_min
* 60;
162 *t
+= tm
.tm_hour
* 60 * 60;
163 *t
+= tm
.tm_mday
* 60 * 60 * 24;
169 cdf_ctime(const time_t *sec
, char *buf
)
171 char *ptr
= ctime_r(sec
, buf
);
174 (void)snprintf(buf
, 26, "*Bad* 0x%16.16" INT64_T_FORMAT
"x\n",
182 main(int argc
, char *argv
[])
186 static const cdf_timestamp_t tst
= 0x01A5E403C2D59C00ULL
;
187 static const char *ref
= "Sat Apr 23 01:30:00 1977";
190 cdf_timestamp_to_timespec(&ts
, tst
);
191 p
= cdf_ctime(&ts
.tv_sec
, buf
);
192 if ((q
= strchr(p
, '\n')) != NULL
)
194 if (strcmp(ref
, p
) != 0)
195 errx(1, "Error date %s != %s\n", ref
, p
);