2 * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #include <openssl/e_os2.h>
12 #include <openssl/crypto.h>
14 struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result)
18 #if defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_MACOSX)
19 if (gmtime_r(timer, result) == NULL)
27 memcpy(result, ts, sizeof(struct tm));
34 * Take a tm structure and add an offset to it. This avoids any OS issues
35 * with restricted date types and overflows which cause the year 2038
39 #define SECS_PER_DAY (24 * 60 * 60)
41 static long date_to_julian(int y, int m, int d);
42 static void julian_to_date(long jd, int *y, int *m, int *d);
43 static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
44 long *pday, int *psec);
46 int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec)
48 int time_sec, time_year, time_month, time_day;
51 /* Convert time and offset into Julian day and seconds */
52 if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec))
55 /* Convert Julian day back to date */
57 julian_to_date(time_jd, &time_year, &time_month, &time_day);
59 if (time_year < 1900 || time_year > 9999)
62 /* Update tm structure */
64 tm->tm_year = time_year - 1900;
65 tm->tm_mon = time_month - 1;
66 tm->tm_mday = time_day;
68 tm->tm_hour = time_sec / 3600;
69 tm->tm_min = (time_sec / 60) % 60;
70 tm->tm_sec = time_sec % 60;
76 int OPENSSL_gmtime_diff(int *pday, int *psec,
77 const struct tm *from, const struct tm *to)
79 int from_sec, to_sec, diff_sec;
80 long from_jd, to_jd, diff_day;
81 if (!julian_adj(from, 0, 0, &from_jd, &from_sec))
83 if (!julian_adj(to, 0, 0, &to_jd, &to_sec))
85 diff_day = to_jd - from_jd;
86 diff_sec = to_sec - from_sec;
87 /* Adjust differences so both positive or both negative */
88 if (diff_day > 0 && diff_sec < 0) {
90 diff_sec += SECS_PER_DAY;
92 if (diff_day < 0 && diff_sec > 0) {
94 diff_sec -= SECS_PER_DAY;
98 *pday = (int)diff_day;
106 /* Convert tm structure and offset into julian day and seconds */
107 static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
108 long *pday, int *psec)
110 int offset_hms, offset_day;
112 int time_year, time_month, time_day;
113 /* split offset into days and day seconds */
114 offset_day = offset_sec / SECS_PER_DAY;
115 /* Avoid sign issues with % operator */
116 offset_hms = offset_sec - (offset_day * SECS_PER_DAY);
117 offset_day += off_day;
118 /* Add current time seconds to offset */
119 offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
120 /* Adjust day seconds if overflow */
121 if (offset_hms >= SECS_PER_DAY) {
123 offset_hms -= SECS_PER_DAY;
124 } else if (offset_hms < 0) {
126 offset_hms += SECS_PER_DAY;
130 * Convert date of time structure into a Julian day number.
133 time_year = tm->tm_year + 1900;
134 time_month = tm->tm_mon + 1;
135 time_day = tm->tm_mday;
137 time_jd = date_to_julian(time_year, time_month, time_day);
139 /* Work out Julian day of new date */
140 time_jd += offset_day;
151 * Convert date to and from julian day Uses Fliegel & Van Flandern algorithm
153 static long date_to_julian(int y, int m, int d)
155 return (1461 * (y + 4800 + (m - 14) / 12)) / 4 +
156 (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 -
157 (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075;
160 static void julian_to_date(long jd, int *y, int *m, int *d)
163 long n = (4 * L) / 146097;
166 L = L - (146097 * n + 3) / 4;
167 i = (4000 * (L + 1)) / 1461001;
168 L = L - (1461 * i) / 4 + 31;
170 *d = L - (2447 * j) / 80;
172 *m = j + 2 - (12 * L);
173 *y = 100 * (n - 49) + i + L;