#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.
/// 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
};

View File

@ -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();

View File

@ -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;
}

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)
{
std::time_t time = timestamp.epochTime();

View File

@ -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;

View File

@ -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;