From 2c15b93dee3d06bcdf50f7aa752898e489d252fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnter=20Obiltschnig?= Date: Mon, 28 Mar 2022 12:57:16 +0200 Subject: [PATCH] #2882: another attempt at fixing it that should also work on other platforms --- Foundation/include/Poco/Timezone.h | 17 ++++------- Foundation/src/LocalDateTime.cpp | 8 +++--- Foundation/src/Timezone_UNIX.cpp | 46 +++++++++++++++++------------- Foundation/src/Timezone_VX.cpp | 6 ++++ Foundation/src/Timezone_WIN32.cpp | 41 +++++++++++++++++++++----- Foundation/src/Timezone_WINCE.cpp | 20 ++++++++++--- 6 files changed, 91 insertions(+), 47 deletions(-) diff --git a/Foundation/include/Poco/Timezone.h b/Foundation/include/Poco/Timezone.h index f64a0c953..308450979 100644 --- a/Foundation/include/Poco/Timezone.h +++ b/Foundation/include/Poco/Timezone.h @@ -38,6 +38,11 @@ public: /// daylight saving time is in use. /// local time = UTC + utcOffset() + dst(). + static int dst(const Poco::Timestamp& timestamp); + /// Returns the daylight saving time offset in seconds if + /// daylight saving time is in use for the given time. + /// local time = UTC + utcOffset() + dst(). + static bool isDst(const Timestamp& timestamp); /// Returns true if daylight saving time is in effect /// for the given time. Depending on the operating system @@ -58,18 +63,6 @@ public: static std::string dstName(); /// Returns the timezone name if daylight saving time is in effect. - -#if !defined(POCO_OS_FAMILY_WINDOWS) - static int utcOffset(const Poco::Timestamp& timestamp); - /// Returns the offset of local time to UTC - /// for the given time, in seconds. - /// local time = UTC + utcOffset() + dst(). - - static int dst(const Poco::Timestamp& timestamp); - /// Returns the daylight saving time offset in seconds if - /// daylight saving time is in use for the given time. - /// local time = UTC + utcOffset() + dst(). -#endif }; diff --git a/Foundation/src/LocalDateTime.cpp b/Foundation/src/LocalDateTime.cpp index 09a73d15c..846ebc7fc 100644 --- a/Foundation/src/LocalDateTime.cpp +++ b/Foundation/src/LocalDateTime.cpp @@ -277,7 +277,7 @@ void LocalDateTime::determineTzd(bool adjust) if (err) broken = nullptr; #endif if (!broken) throw Poco::SystemException("cannot get local time"); - _tzd = (Timezone::utcOffset() + Timezone::dst(_dateTime.timestamp())); + _tzd = Timezone::utcOffset() + Timezone::dst(_dateTime.timestamp()); #else std::tm broken; #if defined(POCO_VXWORKS) && (defined(_VXWORKS_COMPATIBILITY_MODE) || (defined(_WRS_VXWORKS_MAJOR) && ((_WRS_VXWORKS_MAJOR < 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR < 9))))) @@ -287,7 +287,7 @@ void LocalDateTime::determineTzd(bool adjust) if (!localtime_r(&epochTime, &broken)) throw Poco::SystemException("cannot get local time"); #endif - _tzd = (Timezone::utcOffset() + ((broken.tm_isdst == 1) ? 3600 : 0)); + _tzd = Timezone::utcOffset() + Timezone::dst(_dateTime.timestamp()); #endif adjustForTzd(); } @@ -305,8 +305,8 @@ std::time_t LocalDateTime::dstOffset(int& dstOffset) const std::time_t local; std::tm broken; - broken.tm_year = (_dateTime.year() - 1900); - broken.tm_mon = (_dateTime.month() - 1); + broken.tm_year = _dateTime.year() - 1900; + broken.tm_mon = _dateTime.month() - 1; broken.tm_mday = _dateTime.day(); broken.tm_hour = _dateTime.hour(); broken.tm_min = _dateTime.minute(); diff --git a/Foundation/src/Timezone_UNIX.cpp b/Foundation/src/Timezone_UNIX.cpp index 19444a7c1..e03d6f9a5 100644 --- a/Foundation/src/Timezone_UNIX.cpp +++ b/Foundation/src/Timezone_UNIX.cpp @@ -29,12 +29,22 @@ public: tzset(); } - static long gmtOffset(const struct std::tm& t) + int timeZone() { - #if defined(__CYGWIN__) - return t.__TM_GMTOFF; + Poco::FastMutex::ScopedLock lock(_mutex); + + #if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) || POCO_OS == POCO_OS_ANDROID // no timezone global var + std::time_t now = std::time(NULL); + struct std::tm t; + gmtime_r(&now, &t); + std::time_t utc = std::mktime(&t); + return now - utc; + #elif defined(__CYGWIN__) + tzset(); + return -_timezone; #else - return t.tm_gmtoff; + tzset(); + return -timezone; #endif } @@ -54,22 +64,9 @@ private: static TZInfo tzInfo; -int Timezone::utcOffset(const Poco::Timestamp& timestamp) -{ - std::time_t time = timestamp.epochTime(); - struct std::tm local; - if (!localtime_r(&time, &local)) - throw Poco::SystemException("cannot get UTC offset"); - struct std::tm utc; - gmtime_r(&time, &utc); - std::time_t utctime = std::mktime(&utc); - return time - utctime; -} - - int Timezone::utcOffset() { - return utcOffset(Poco::Timestamp()); + return tzInfo.timeZone(); } @@ -85,8 +82,17 @@ int Timezone::dst(const Poco::Timestamp& timestamp) struct std::tm local; if (!localtime_r(&time, &local)) throw Poco::SystemException("cannot get local time DST offset"); - long dst = TZInfo::gmtOffset(local) - utcOffset(timestamp); - return local.tm_isdst == 1 ? dst : 0; + if (local.tm_isdst > 0) + { +#if defined(__CYGWIN__) + return local.__TM_GMTOFF - utcOffset(); +#elif defined(_BSD_SOURCE) || defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) || POCO_OS == POCO_OS_ANDROID + return local.tm_gmtoff - utcOffset(); +#else + return 3600; +#endif + } + else return 0; } diff --git a/Foundation/src/Timezone_VX.cpp b/Foundation/src/Timezone_VX.cpp index cfb4170a9..4601dd21c 100644 --- a/Foundation/src/Timezone_VX.cpp +++ b/Foundation/src/Timezone_VX.cpp @@ -45,6 +45,12 @@ int Timezone::dst() } +int Timezone::dst(const Poco::Timestamp& timestamp) +{ + return isDst(timestamp) ? 3600 : 0; +} + + bool Timezone::isDst(const Timestamp& timestamp) { std::time_t time = timestamp.epochTime(); diff --git a/Foundation/src/Timezone_WIN32.cpp b/Foundation/src/Timezone_WIN32.cpp index 8fdc77e8f..a510bca9b 100644 --- a/Foundation/src/Timezone_WIN32.cpp +++ b/Foundation/src/Timezone_WIN32.cpp @@ -29,7 +29,7 @@ int Timezone::utcOffset() return -tzInfo.Bias*60; } - + int Timezone::dst() { TIME_ZONE_INFORMATION tzInfo; @@ -38,15 +38,42 @@ int Timezone::dst() } +int Timezone::dst(const Poco::Timestamp& timestamp) +{ + if (isDst(timestamp)) + { + TIME_ZONE_INFORMATION tzInfo; + GetTimeZoneInformation(&tzInfo); + return -tzInfo.DaylightBias*60; + } + else return 0; +} + + bool Timezone::isDst(const Timestamp& timestamp) { std::time_t time = timestamp.epochTime(); - struct std::tm* tms = std::localtime(&time); - if (!tms) throw Poco::SystemException("cannot get local time DST flag"); - return tms->tm_isdst > 0; + struct std::tm local; + if (localtime_s(&local, &time)) + throw Poco::SystemException("cannot get local time DST flag"); + return local.tm_isdst > 0; } - + +int Timezone::utcOffset(const Poco::Timestamp& timestamp) +{ + std::time_t time = timestamp.epochTime(); + struct tm local; + if (localtime_s(&local, &time)) + throw Poco::SystemException("cannot get UTC offset"); + struct tm utc; + if (gmtime_s(&utc, &time)) + throw Poco::SystemException("cannot get UTC offset"); + std::time_t utctime = std::mktime(&utc); + return time - utctime; +} + + std::string Timezone::name() { std::string result; @@ -57,7 +84,7 @@ std::string Timezone::name() return result; } - + std::string Timezone::standardName() { std::string result; @@ -68,7 +95,7 @@ std::string Timezone::standardName() return result; } - + std::string Timezone::dstName() { std::string result; diff --git a/Foundation/src/Timezone_WINCE.cpp b/Foundation/src/Timezone_WINCE.cpp index fb794f58b..99ae9ce3f 100644 --- a/Foundation/src/Timezone_WINCE.cpp +++ b/Foundation/src/Timezone_WINCE.cpp @@ -34,7 +34,7 @@ int Timezone::utcOffset() return -tzInfo.Bias*60; } - + int Timezone::dst() { TIME_ZONE_INFORMATION tzInfo; @@ -43,6 +43,18 @@ int Timezone::dst() } +int Timezone::dst(const Poco::Timestamp& timestamp) +{ + if (isDst(timestamp)) + { + TIME_ZONE_INFORMATION tzInfo; + GetTimeZoneInformation(&tzInfo); + return -tzInfo.DaylightBias*60; + } + else return 0; +} + + bool Timezone::isDst(const Timestamp& timestamp) { std::time_t time = timestamp.epochTime(); @@ -55,7 +67,7 @@ bool Timezone::isDst(const Timestamp& timestamp) return tms->tm_isdst > 0; } - + std::string Timezone::name() { std::string result; @@ -66,7 +78,7 @@ std::string Timezone::name() return result; } - + std::string Timezone::standardName() { std::string result; @@ -77,7 +89,7 @@ std::string Timezone::standardName() return result; } - + std::string Timezone::dstName() { std::string result;