Skip to content

Instantly share code, notes, and snippets.

@anba

anba/time.cpp Secret

Created July 22, 2019 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anba/14f2a7982f5010dbae90bb3509774ced to your computer and use it in GitHub Desktop.
Save anba/14f2a7982f5010dbae90bb3509774ced to your computer and use it in GitHub Desktop.
// See https://searchfox.org/mozilla-central/source/js/src/vm/DateTime.cpp
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <time.h>
#include <iostream>
#if !defined(XP_WIN)
# include <limits.h>
# include <unistd.h>
#endif /* !defined(XP_WIN) */
#define HAVE_LOCALTIME_R 1
static bool ComputeLocalTime(time_t local, struct tm* ptm) {
#if defined(_WIN32)
return localtime_s(ptm, &local) == 0;
#elif defined(HAVE_LOCALTIME_R)
return localtime_r(&local, ptm);
#else
struct tm* otm = localtime(&local);
if (!otm) {
return false;
}
*ptm = *otm;
return true;
#endif
}
static bool ComputeUTCTime(time_t t, struct tm* ptm) {
#if defined(_WIN32)
return gmtime_s(ptm, &t) == 0;
#elif defined(HAVE_GMTIME_R)
return gmtime_r(&t, ptm);
#else
struct tm* otm = gmtime(&t);
if (!otm) {
return false;
}
*ptm = *otm;
return true;
#endif
}
static int32_t UTCToLocalStandardOffsetSeconds() {
constexpr double SecondsPerMinute = 60;
constexpr unsigned SecondsPerHour = 60 * 60;
constexpr unsigned SecondsPerDay = SecondsPerHour * 24;
time_t currentMaybeWithDST = time(nullptr);
if (currentMaybeWithDST == time_t(-1)) {
return 0;
}
struct tm local;
if (!ComputeLocalTime(currentMaybeWithDST, &local)) {
return 0;
}
time_t currentNoDST;
if (local.tm_isdst == 0) {
currentNoDST = currentMaybeWithDST;
} else {
struct tm localNoDST = local;
localNoDST.tm_isdst = 0;
currentNoDST = mktime(&localNoDST);
if (currentNoDST == time_t(-1)) {
return 0;
}
}
struct tm utc;
if (!ComputeUTCTime(currentNoDST, &utc)) {
return 0;
}
int utc_secs = utc.tm_hour * SecondsPerHour + utc.tm_min * SecondsPerMinute;
int local_secs = local.tm_hour * SecondsPerHour + local.tm_min * SecondsPerMinute;
if (utc.tm_mday == local.tm_mday) {
return local_secs - utc_secs;
}
if (utc_secs > local_secs) {
return (SecondsPerDay + local_secs) - utc_secs;
}
return local_secs - (utc_secs + SecondsPerDay);
}
int main() {
do {
std::cout << "current time zone offset: " << UTCToLocalStandardOffsetSeconds() << std::endl;
} while (std::cin.get() == '\n');
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment