xref: /haiku/src/system/libroot/posix/time/localtime.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
1 /*
2  * Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <errno.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <time.h>
11 
12 #include <syscalls.h>
13 
14 #include <StorageDefs.h>
15 
16 #include <errno_private.h>
17 #include "LocaleBackend.h"
18 
19 
20 using BPrivate::Libroot::GetCurrentLocaleBackend;
21 using BPrivate::Libroot::LocaleBackend;
22 
23 
24 static char sStandardTZName[64] 		= { "GMT" };
25 static char sDaylightSavingTZName[64]	= { "GMT" };
26 
27 
28 char* tzname[2] = {
29 	sStandardTZName,
30 	sDaylightSavingTZName
31 };
32 long timezone = 0;
33 int daylight = 0;
34 
35 
36 // These three functions are used as a fallback when the locale backend could not
37 // be loaded. They are implemented in localtime_fading_out.c.
38 extern "C" struct tm* __gmtime_r_fallback(const time_t* timep, struct tm* tmp);
39 extern "C" time_t __mktime_fallback(struct tm* tmp);
40 extern "C" time_t __timegm_fallback(struct tm* tmp);
41 
42 
43 extern "C" void
44 tzset(void)
45 {
46 	if (GetCurrentLocaleBackend() == NULL && LocaleBackend::LoadBackend() != B_OK)
47 		return;
48 
49 	char timeZoneID[B_FILE_NAME_LENGTH] = { "GMT" };
50 	_kern_get_timezone(NULL, timeZoneID, sizeof(timeZoneID));
51 
52 	GetCurrentLocaleBackend()->TZSet(timeZoneID, getenv("TZ"));
53 }
54 
55 
56 extern "C" struct tm*
57 localtime(const time_t* inTime)
58 {
59 	static tm tm;
60 
61 	return localtime_r(inTime, &tm);
62 }
63 
64 
65 extern "C" struct tm*
66 localtime_r(const time_t* inTime, struct tm* tmOut)
67 {
68 	if (inTime == NULL) {
69 		__set_errno(EINVAL);
70 		return NULL;
71 	}
72 
73 	tzset();
74 
75 	LocaleBackend* backend = GetCurrentLocaleBackend();
76 
77 	if (backend != NULL) {
78 		status_t status = backend->Localtime(inTime, tmOut);
79 
80 		if (status != B_OK)
81 			__set_errno(EOVERFLOW);
82 
83 		return tmOut;
84 	}
85 
86 	// without a locale backend, there are no timezones, so we fall back to
87 	// using a basic gmtime_r implementation.
88 	return __gmtime_r_fallback(inTime, tmOut);
89 }
90 
91 
92 extern "C" struct tm*
93 gmtime(const time_t* inTime)
94 {
95 	static tm tm;
96 
97 	return gmtime_r(inTime, &tm);
98 }
99 
100 
101 extern "C" struct tm*
102 gmtime_r(const time_t* inTime, struct tm* tmOut)
103 {
104 	if (inTime == NULL) {
105 		__set_errno(EINVAL);
106 		return NULL;
107 	}
108 
109 	tzset();
110 
111 	LocaleBackend* backend = GetCurrentLocaleBackend();
112 
113 	if (backend != NULL) {
114 		status_t status = backend->Gmtime(inTime, tmOut);
115 
116 		if (status != B_OK)
117 			__set_errno(EOVERFLOW);
118 
119 		return tmOut;
120 	}
121 
122 	// without a locale backend, we fall back to using a basic gmtime_r
123 	// implementation.
124 	return __gmtime_r_fallback(inTime, tmOut);
125 }
126 
127 
128 extern "C" time_t
129 mktime(struct tm* inTm)
130 {
131 	if (inTm == NULL) {
132 		__set_errno(EINVAL);
133 		return -1;
134 	}
135 
136 	tzset();
137 
138 	LocaleBackend* backend = GetCurrentLocaleBackend();
139 
140 	if (backend != NULL) {
141 		time_t timeOut;
142 		status_t status = backend->Mktime(inTm, timeOut);
143 
144 		if (status != B_OK) {
145 			__set_errno(EOVERFLOW);
146 			return -1;
147 		}
148 
149 		return timeOut;
150 	}
151 
152 	// without a locale backend, we fall back to using a basic gmtime_r
153 	// implementation.
154 	return __mktime_fallback(inTm);
155 }
156 
157 
158 extern "C" time_t
159 timegm(struct tm* inTm)
160 {
161 	if (inTm == NULL) {
162 		__set_errno(EINVAL);
163 		return -1;
164 	}
165 	tzset();
166 
167 	LocaleBackend* backend = GetCurrentLocaleBackend();
168 
169 	if (backend != NULL) {
170 		time_t timeOut;
171 		status_t status = backend->Timegm(inTm, timeOut);
172 
173 		if (status != B_OK) {
174 			__set_errno(EOVERFLOW);
175 			return -1;
176 		}
177 
178 		return timeOut;
179 	}
180 
181 	// without a locale backend, we fall back to using a basic timegm
182 	// implementation.
183 	return __timegm_fallback(inTm);
184 }
185