#2882: another attempt at fixing it that should also work on other platforms

This commit is contained in:
Günter Obiltschnig 2022-03-28 12:57:16 +02:00
parent 6aa29ade17
commit 2c15b93dee
6 changed files with 91 additions and 47 deletions

View File

@ -38,6 +38,11 @@ public:
/// daylight saving time is in use. /// daylight saving time is in use.
/// local time = UTC + utcOffset() + dst(). /// 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); static bool isDst(const Timestamp& timestamp);
/// Returns true if daylight saving time is in effect /// Returns true if daylight saving time is in effect
/// for the given time. Depending on the operating system /// for the given time. Depending on the operating system
@ -58,18 +63,6 @@ public:
static std::string dstName(); static std::string dstName();
/// Returns the timezone name if daylight saving time is in effect. /// 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
}; };

View File

@ -277,7 +277,7 @@ void LocalDateTime::determineTzd(bool adjust)
if (err) broken = nullptr; if (err) broken = nullptr;
#endif #endif
if (!broken) throw Poco::SystemException("cannot get local time"); if (!broken) throw Poco::SystemException("cannot get local time");
_tzd = (Timezone::utcOffset() + Timezone::dst(_dateTime.timestamp())); _tzd = Timezone::utcOffset() + Timezone::dst(_dateTime.timestamp());
#else #else
std::tm broken; 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))))) #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)) if (!localtime_r(&epochTime, &broken))
throw Poco::SystemException("cannot get local time"); throw Poco::SystemException("cannot get local time");
#endif #endif
_tzd = (Timezone::utcOffset() + ((broken.tm_isdst == 1) ? 3600 : 0)); _tzd = Timezone::utcOffset() + Timezone::dst(_dateTime.timestamp());
#endif #endif
adjustForTzd(); adjustForTzd();
} }
@ -305,8 +305,8 @@ std::time_t LocalDateTime::dstOffset(int& dstOffset) const
std::time_t local; std::time_t local;
std::tm broken; std::tm broken;
broken.tm_year = (_dateTime.year() - 1900); broken.tm_year = _dateTime.year() - 1900;
broken.tm_mon = (_dateTime.month() - 1); broken.tm_mon = _dateTime.month() - 1;
broken.tm_mday = _dateTime.day(); broken.tm_mday = _dateTime.day();
broken.tm_hour = _dateTime.hour(); broken.tm_hour = _dateTime.hour();
broken.tm_min = _dateTime.minute(); broken.tm_min = _dateTime.minute();

View File

@ -29,12 +29,22 @@ public:
tzset(); tzset();
} }
static long gmtOffset(const struct std::tm& t) int timeZone()
{ {
#if defined(__CYGWIN__) Poco::FastMutex::ScopedLock lock(_mutex);
return t.__TM_GMTOFF;
#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 #else
return t.tm_gmtoff; tzset();
return -timezone;
#endif #endif
} }
@ -54,22 +64,9 @@ private:
static TZInfo tzInfo; 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() 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; struct std::tm local;
if (!localtime_r(&time, &local)) if (!localtime_r(&time, &local))
throw Poco::SystemException("cannot get local time DST offset"); throw Poco::SystemException("cannot get local time DST offset");
long dst = TZInfo::gmtOffset(local) - utcOffset(timestamp); if (local.tm_isdst > 0)
return local.tm_isdst == 1 ? dst : 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;
} }

View File

@ -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) bool Timezone::isDst(const Timestamp& timestamp)
{ {
std::time_t time = timestamp.epochTime(); std::time_t time = timestamp.epochTime();

View File

@ -38,12 +38,39 @@ 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) bool Timezone::isDst(const Timestamp& timestamp)
{ {
std::time_t time = timestamp.epochTime(); std::time_t time = timestamp.epochTime();
struct std::tm* tms = std::localtime(&time); struct std::tm local;
if (!tms) throw Poco::SystemException("cannot get local time DST flag"); if (localtime_s(&local, &time))
return tms->tm_isdst > 0; 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;
} }

View File

@ -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) bool Timezone::isDst(const Timestamp& timestamp)
{ {
std::time_t time = timestamp.epochTime(); std::time_t time = timestamp.epochTime();