summaryrefslogtreecommitdiff
path: root/src/time/mktime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/time/mktime.c')
-rw-r--r--src/time/mktime.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/src/time/mktime.c b/src/time/mktime.c
index 858cd50d..e38b4619 100644
--- a/src/time/mktime.c
+++ b/src/time/mktime.c
@@ -1,24 +1,30 @@
-#include <time.h>
-
-#include "__time.h"
+#include "time_impl.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
time_t mktime(struct tm *tm)
{
- int isdst = tm->tm_isdst;
- time_t t, lt;
+ struct tm new;
+ long opp;
+ long long t = __tm_to_secs(tm);
+
+ __secs_to_zone(t, 1, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);
- __tzset();
+ if (tm->tm_isdst>=0 && new.tm_isdst!=tm->tm_isdst)
+ t += opp - new.__tm_gmtoff;
- tm->tm_sec += __timezone;
- if (isdst > 0) tm->tm_sec += __dst_offset;
+ t += new.__tm_gmtoff;
+ if ((time_t)t != t) goto error;
- t = __tm_to_time(tm);
-
- lt = t - __timezone;
- if (isdst > 0) lt -= __dst_offset;
- __time_to_tm(lt, tm);
+ __secs_to_zone(t, 0, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);
- __dst_adjust(tm);
-
+ if (__secs_to_tm(t - new.__tm_gmtoff, &new) < 0) goto error;
+
+ *tm = new;
return t;
+
+error:
+ errno = EINVAL;
+ return -1;
}