xref: /haiku/src/system/libroot/posix/time/localtime_fallback.c (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
1 /* The following methods were adapted from musl.
2  * See musl/COPYRIGHT for license information. */
3 
4 #include <errno.h>
5 
6 #include "../musl/time/time_impl.h"
7 
8 
9 static long  __timezone = 0;
10 static int dst_off = 0;
11 const char __utc[] = "UTC";
12 static const char *__tzname[2] = { __utc, __utc };
13 
14 
15 static void
16 __secs_to_zone(long long t, int local, int *isdst, int *offset, long *oppoff, const char **zonename)
17 {
18 	*isdst = 0;
19 	*offset = -__timezone;
20 	if (oppoff) *oppoff = -dst_off;
21 	*zonename = __tzname[0];
22 }
23 
24 
25 struct tm *
26 __gmtime_r_fallback(const time_t *restrict t, struct tm *restrict tm)
27 {
28 	if (__secs_to_tm(*t, tm) < 0) {
29 		errno = EOVERFLOW;
30 		return 0;
31 	}
32 	tm->tm_isdst = 0;
33 	tm->__tm_gmtoff = 0;
34 	tm->__tm_zone = __utc;
35 	return tm;
36 }
37 
38 
39 time_t
40 __mktime_fallback(struct tm *tm)
41 {
42 	struct tm new;
43 	long opp;
44 	long long t = __tm_to_secs(tm);
45 
46 	__secs_to_zone(t, 1, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);
47 
48 	if (tm->tm_isdst>=0 && new.tm_isdst!=tm->tm_isdst)
49 		t -= opp - new.__tm_gmtoff;
50 
51 	t -= new.__tm_gmtoff;
52 	if ((time_t)t != t) goto error;
53 
54 	__secs_to_zone(t, 0, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);
55 
56 	if (__secs_to_tm(t + new.__tm_gmtoff, &new) < 0) goto error;
57 
58 	*tm = new;
59 	return t;
60 
61 error:
62 	errno = EOVERFLOW;
63 	return -1;
64 }
65 
66 
67 time_t
68 __timegm_fallback(struct tm *tm)
69 {
70 	struct tm new;
71 	long long t = __tm_to_secs(tm);
72 	if (__secs_to_tm(t, &new) < 0) {
73 		errno = EOVERFLOW;
74 		return -1;
75 	}
76 	*tm = new;
77 	tm->tm_isdst = 0;
78 	tm->__tm_gmtoff = 0;
79 	tm->__tm_zone = __utc;
80 	return t;
81 }
82