Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
duk_bi_date_unix.c File Reference
#include "duk_internal.h"

Go to the source code of this file.

Macros

#define DUK__STRPTIME_BUF_SIZE   64
 
#define DUK__STRFTIME_BUF_SIZE   64
 

Functions

DUK_INTERNAL duk_double_t duk_bi_date_get_now_time (duk_context *ctx)
 
DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime (duk_double_t d)
 

Macro Definition Documentation

◆ DUK__STRFTIME_BUF_SIZE

#define DUK__STRFTIME_BUF_SIZE   64

◆ DUK__STRPTIME_BUF_SIZE

#define DUK__STRPTIME_BUF_SIZE   64

Function Documentation

◆ duk_bi_date_get_local_tzoffset_gmtime()

DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime ( duk_double_t d)

Definition at line 49 of file duktape-1.5.2/src-separate/duk_bi_date_unix.c.

49 {
50 time_t t, t1, t2;
53 struct tm tms[2];
54#ifdef DUK_USE_DATE_TZO_GMTIME
55 struct tm *tm_ptr;
56#endif
57
58 /* For NaN/inf, the return value doesn't matter. */
59 if (!DUK_ISFINITE(d)) {
60 return 0;
61 }
62
63 /* If not within Ecmascript range, some integer time calculations
64 * won't work correctly (and some asserts will fail), so bail out
65 * if so. This fixes test-bug-date-insane-setyear.js. There is
66 * a +/- 24h leeway in this range check to avoid a test262 corner
67 * case documented in test-bug-date-timeval-edges.js.
68 */
70 DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
71 return 0;
72 }
73
74 /*
75 * This is a bit tricky to implement portably. The result depends
76 * on the timestamp (specifically, DST depends on the timestamp).
77 * If e.g. UNIX APIs are used, they'll have portability issues with
78 * very small and very large years.
79 *
80 * Current approach:
81 *
82 * - Stay within portable UNIX limits by using equivalent year mapping.
83 * Avoid year 1970 and 2038 as some conversions start to fail, at
84 * least on some platforms. Avoiding 1970 means that there are
85 * currently DST discrepancies for 1970.
86 *
87 * - Create a UTC and local time breakdowns from 't'. Then create
88 * a time_t using gmtime() and localtime() and compute the time
89 * difference between the two.
90 *
91 * Equivalent year mapping (E5 Section 15.9.1.8):
92 *
93 * If the host environment provides functionality for determining
94 * daylight saving time, the implementation of ECMAScript is free
95 * to map the year in question to an equivalent year (same
96 * leap-year-ness and same starting week day for the year) for which
97 * the host environment provides daylight saving time information.
98 * The only restriction is that all equivalent years should produce
99 * the same result.
100 *
101 * This approach is quite reasonable but not entirely correct, e.g.
102 * the specification also states (E5 Section 15.9.1.8):
103 *
104 * The implementation of ECMAScript should not try to determine
105 * whether the exact time was subject to daylight saving time, but
106 * just whether daylight saving time would have been in effect if
107 * the _current daylight saving time algorithm_ had been used at the
108 * time. This avoids complications such as taking into account the
109 * years that the locale observed daylight saving time year round.
110 *
111 * Since we rely on the platform APIs for conversions between local
112 * time and UTC, we can't guarantee the above. Rather, if the platform
113 * has historical DST rules they will be applied. This seems to be the
114 * general preferred direction in Ecmascript standardization (or at least
115 * implementations) anyway, and even the equivalent year mapping should
116 * be disabled if the platform is known to handle DST properly for the
117 * full Ecmascript range.
118 *
119 * The following has useful discussion and links:
120 *
121 * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
122 */
123
124 duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
125 DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
126
127 d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
128 DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */
129 t = (time_t) (d / 1000.0);
130 DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
131
132 DUK_MEMZERO((void *) tms, sizeof(struct tm) * 2);
133
134#if defined(DUK_USE_DATE_TZO_GMTIME_R)
135 (void) gmtime_r(&t, &tms[0]);
136 (void) localtime_r(&t, &tms[1]);
137#elif defined(DUK_USE_DATE_TZO_GMTIME)
138 tm_ptr = gmtime(&t);
139 DUK_MEMCPY((void *) &tms[0], tm_ptr, sizeof(struct tm));
140 tm_ptr = localtime(&t);
141 DUK_MEMCPY((void *) &tms[1], tm_ptr, sizeof(struct tm));
142#else
143#error internal error
144#endif
145 DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
146 "wday:%ld,yday:%ld,isdst:%ld}",
147 (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
148 (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
149 (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
150 DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
151 "wday:%ld,yday:%ld,isdst:%ld}",
152 (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
153 (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
154 (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
155
156 /* tm_isdst is both an input and an output to mktime(), use 0 to
157 * avoid DST handling in mktime():
158 * - https://github.com/svaarala/duktape/issues/406
159 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
160 */
161 tms[0].tm_isdst = 0;
162 tms[1].tm_isdst = 0;
163 t1 = mktime(&tms[0]); /* UTC */
164 t2 = mktime(&tms[1]); /* local */
165 if (t1 == (time_t) -1 || t2 == (time_t) -1) {
166 /* This check used to be for (t < 0) but on some platforms
167 * time_t is unsigned and apparently the proper way to detect
168 * an mktime() error return is the cast above. See e.g.:
169 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
170 */
171 goto error;
172 }
173 DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
174
175 /* Compute final offset in seconds, positive if local time ahead of
176 * UTC (returned value is UTC-to-local offset).
177 *
178 * difftime() returns a double, so coercion to int generates quite
179 * a lot of code. Direct subtraction is not portable, however.
180 * XXX: allow direct subtraction on known platforms.
181 */
182#if 0
183 return (duk_int_t) (t2 - t1);
184#endif
185 return (duk_int_t) difftime(t2, t1);
186
187 error:
188 /* XXX: return something more useful, so that caller can throw? */
189 DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
190 return 0;
191}
duk_int_fast32_t duk_int_t
#define DUK_MEMZERO(p, n)
DUK_INTERNAL_DECL void duk_bi_date_timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags)
DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x)
DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags)
#define DUK_DATE_FLAG_EQUIVYEAR
#define DUK_DATE_IDX_NUM_PARTS
static void error(LoadState *S, const char *why)

References DUK_ASSERT, duk_bi_date_get_timeval_from_dparts(), duk_bi_date_timeval_in_leeway_range(), duk_bi_date_timeval_to_parts(), DUK_D, DUK_DATE_FLAG_EQUIVYEAR, DUK_DATE_IDX_NUM_PARTS, DUK_DATE_IDX_YEAR, DUK_DD, DUK_DDD, DUK_DDDPRINT, DUK_DDPRINT, DUK_DPRINT, DUK_ISFINITE, DUK_MEMCPY, DUK_MEMZERO, and error().

◆ duk_bi_date_get_now_time()

DUK_INTERNAL duk_double_t duk_bi_date_get_now_time ( duk_context * ctx)

Definition at line 38 of file duktape-1.5.2/src-separate/duk_bi_date_unix.c.

38 {
39 time_t t;
40
41 DUK_UNREF(ctx);
42 t = time(NULL);
43 return ((duk_double_t) t) * 1000.0;
44}
#define NULL
Definition gmacros.h:924

References DUK_UNREF, and NULL.