mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
3.4 KiB
98 lines
3.4 KiB
/*
|
|
* Windows Date providers
|
|
*
|
|
* Platform specific links:
|
|
*
|
|
* - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
|
|
*/
|
|
|
|
#include "duk_internal.h"
|
|
|
|
/* The necessary #includes are in place in duk_config.h. */
|
|
|
|
#if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
|
|
/* Shared Windows helpers. */
|
|
DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
|
|
FILETIME ft;
|
|
if (SystemTimeToFileTime(st, &ft) == 0) {
|
|
DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
|
|
res->QuadPart = 0;
|
|
} else {
|
|
res->LowPart = ft.dwLowDateTime;
|
|
res->HighPart = ft.dwHighDateTime;
|
|
}
|
|
}
|
|
DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
|
|
DUK_MEMZERO((void *) st, sizeof(*st));
|
|
st->wYear = 1970;
|
|
st->wMonth = 1;
|
|
st->wDayOfWeek = 4; /* not sure whether or not needed; Thursday */
|
|
st->wDay = 1;
|
|
DUK_ASSERT(st->wHour == 0);
|
|
DUK_ASSERT(st->wMinute == 0);
|
|
DUK_ASSERT(st->wSecond == 0);
|
|
DUK_ASSERT(st->wMilliseconds == 0);
|
|
}
|
|
#endif /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
|
|
|
|
#if defined(DUK_USE_DATE_NOW_WINDOWS)
|
|
DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(duk_context *ctx) {
|
|
/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
|
|
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
|
|
*/
|
|
SYSTEMTIME st1, st2;
|
|
ULARGE_INTEGER tmp1, tmp2;
|
|
|
|
DUK_UNREF(ctx);
|
|
|
|
GetSystemTime(&st1);
|
|
duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
|
|
|
|
duk__set_systime_jan1970(&st2);
|
|
duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
|
|
|
|
/* Difference is in 100ns units, convert to milliseconds w/o fractions */
|
|
return (duk_double_t) ((tmp1.QuadPart - tmp2.QuadPart) / 10000LL);
|
|
}
|
|
#endif /* DUK_USE_DATE_NOW_WINDOWS */
|
|
|
|
|
|
#if defined(DUK_USE_DATE_TZO_WINDOWS)
|
|
DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
|
|
SYSTEMTIME st1;
|
|
SYSTEMTIME st2;
|
|
SYSTEMTIME st3;
|
|
ULARGE_INTEGER tmp1;
|
|
ULARGE_INTEGER tmp2;
|
|
ULARGE_INTEGER tmp3;
|
|
FILETIME ft1;
|
|
|
|
/* XXX: handling of timestamps outside Windows supported range.
|
|
* How does Windows deal with dates before 1600? Does windows
|
|
* support all Ecmascript years (like -200000 and +200000)?
|
|
* Should equivalent year mapping be used here too? If so, use
|
|
* a shared helper (currently integrated into timeval-to-parts).
|
|
*/
|
|
|
|
/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
|
|
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
|
|
*/
|
|
|
|
duk__set_systime_jan1970(&st1);
|
|
duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
|
|
tmp2.QuadPart = (ULONGLONG) (d * 10000.0); /* millisec -> 100ns units since jan 1, 1970 */
|
|
tmp2.QuadPart += tmp1.QuadPart; /* input 'd' in Windows UTC, 100ns units */
|
|
|
|
ft1.dwLowDateTime = tmp2.LowPart;
|
|
ft1.dwHighDateTime = tmp2.HighPart;
|
|
FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
|
|
if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
|
|
DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
|
|
return 0;
|
|
}
|
|
duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
|
|
|
|
/* Positive if local time ahead of UTC. */
|
|
return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000000LL); /* seconds */
|
|
}
|
|
#endif /* DUK_USE_DATE_TZO_WINDOWS */
|
|
|