77// ===----------------------------------------------------------------------===//
88
99#include " src/time/time_utils.h"
10+ #include " src/time/timezone.h"
1011#include " src/__support/CPP/limits.h" // INT_MIN, INT_MAX
1112#include " src/__support/common.h"
1213#include " src/__support/macros/config.h"
14+ #include " src/__support/CPP/string_view.h"
1315#include < stdio.h>
16+ #include < stdlib.h>
1417
1518namespace LIBC_NAMESPACE_DECL {
1619namespace time_utils {
@@ -29,9 +32,10 @@ static int64_t computeRemainingYears(int64_t daysPerYears,
2932
3033volatile int file_usage = 0 ;
3134
32- void release_file (FILE *fp) {
35+ void release_file (FILE *fp, char *timezone ) {
3336 file_usage = 0 ;
3437 fclose (fp);
38+ free (timezone);
3539}
3640
3741void acquire_file (FILE *fp, char *timezone, size_t timezone_size) {
@@ -43,7 +47,7 @@ void acquire_file(FILE *fp, char *timezone, size_t timezone_size) {
4347 }
4448
4549 if (fgets (timezone, (int )timezone_size, fp) == NULL ) {
46- release_file (fp);
50+ release_file (fp, timezone );
4751 }
4852}
4953
@@ -150,27 +154,25 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
150154 if (years > INT_MAX || years < INT_MIN)
151155 return time_utils::out_of_range ();
152156
153- char timezone[ TimeConstants::TIMEZONE_SIZE] ;
154-
157+ char * timezone = ( char *) malloc ( sizeof ( char ) * TimeConstants::TIMEZONE_SIZE) ;
158+ timezone = getenv ( " TZ " );
155159 FILE *fp = NULL ;
156- fp = fopen (" /etc/timezone" , " rb" );
157- if (fp == NULL ) {
158- // TODO: implement getting timezone from `TZ` environment variable and
159- // storing the value in `timezone`
160- } else {
160+ if (timezone == NULL ) {
161+ timezone = (char *)realloc (timezone, sizeof (char ) * TimeConstants::TIMEZONE_SIZE);
162+ fp = fopen (" /etc/timezone" , " rb" );
163+ if (fp == NULL ) {
164+ return time_utils::out_of_range ();
165+ }
166+
161167 acquire_file (fp, timezone, TimeConstants::TIMEZONE_SIZE);
162168 }
163169
164- if (file_usage == 0 ) {
165- release_file (fp);
170+ if (fp != NULL && file_usage == 0 ) {
171+ release_file (fp, timezone );
166172 return time_utils::out_of_range ();
167173 }
168174
169- // UTC = 0
170- int offset = 0 ;
171- // TODO: Add more timezones
172- if (internal::same_string (timezone, " Europe/Berlin" ) == 0 )
173- offset = 1 ;
175+ int offset = timezone::get_timezone_offset (timezone);
174176
175177 // All the data (years, month and remaining days) was calculated from
176178 // March, 2000. Thus adjust the data to be from January, 1900.
@@ -189,12 +191,17 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
189191 static_cast <int >(remainingSeconds % TimeConstants::SECONDS_PER_MIN);
190192
191193 set_dst (tm);
192- if (tm->tm_isdst > 0 ) {
194+ if (tm->tm_isdst > 0 && offset != 0 ) {
193195 tm->tm_hour += 1 ;
194196 }
195- tm->tm_hour += offset;
196197
197- release_file (fp);
198+ if (offset != 0 ) {
199+ tm->tm_hour += offset;
200+ }
201+
202+ if (file_usage == 1 ) {
203+ release_file (fp, timezone);
204+ }
198205
199206 return 0 ;
200207}
0 commit comments