mirror of
https://github.com/pocoproject/poco.git
synced 2025-02-23 07:12:45 +01:00
#3509: fix dst and utcOffset handling for Dublin time zone
This commit is contained in:
parent
1b5de92f09
commit
6aa29ade17
@ -58,6 +58,18 @@ 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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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() + ((broken->tm_isdst == 1) ? 3600 : 0));
|
_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)))))
|
||||||
@ -318,7 +318,7 @@ std::time_t LocalDateTime::dstOffset(int& dstOffset) const
|
|||||||
local = std::mktime(&broken);
|
local = std::mktime(&broken);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dstOffset = (broken.tm_isdst == 1) ? 3600 : 0;
|
dstOffset = (broken.tm_isdst == 1) ? Timezone::dst(_dateTime.timestamp()) : 0;
|
||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,22 +29,12 @@ public:
|
|||||||
tzset();
|
tzset();
|
||||||
}
|
}
|
||||||
|
|
||||||
int timeZone()
|
static long gmtOffset(const struct std::tm& t)
|
||||||
{
|
{
|
||||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
#if defined(__CYGWIN__)
|
||||||
|
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
|
||||||
tzset();
|
return t.tm_gmtoff;
|
||||||
return -timezone;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,19 +54,39 @@ 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 tzInfo.timeZone();
|
return utcOffset(Poco::Timestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Timezone::dst()
|
int Timezone::dst()
|
||||||
{
|
{
|
||||||
std::time_t now = std::time(NULL);
|
return dst(Poco::Timestamp());
|
||||||
struct std::tm t;
|
}
|
||||||
if (!localtime_r(&now, &t))
|
|
||||||
|
|
||||||
|
int Timezone::dst(const Poco::Timestamp& timestamp)
|
||||||
|
{
|
||||||
|
std::time_t time = timestamp.epochTime();
|
||||||
|
struct std::tm local;
|
||||||
|
if (!localtime_r(&time, &local))
|
||||||
throw Poco::SystemException("cannot get local time DST offset");
|
throw Poco::SystemException("cannot get local time DST offset");
|
||||||
return t.tm_isdst == 1 ? 3600 : 0;
|
long dst = TZInfo::gmtOffset(local) - utcOffset(timestamp);
|
||||||
|
return local.tm_isdst == 1 ? dst : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -454,6 +454,37 @@ void LocalDateTimeTest::testTimezone()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LocalDateTimeTest::testTimezone2()
|
||||||
|
{
|
||||||
|
#if defined(POCO_OS_FAMILY_UNIX)
|
||||||
|
std::vector<std::string> timezones = {
|
||||||
|
"/usr/share/zoneinfo/America/Los_Angeles",
|
||||||
|
"/usr/share/zoneinfo/Europe/London",
|
||||||
|
"/usr/share/zoneinfo/Europe/Dublin", // special winter time of Ireland
|
||||||
|
"/usr/share/zoneinfo/Europe/Prague",
|
||||||
|
};
|
||||||
|
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
for (const std::string& tz : timezones)
|
||||||
|
{
|
||||||
|
setenv("TZ", tz.c_str(), 1); // POSIX-specific
|
||||||
|
std::vector<LocalDateTime> times = {
|
||||||
|
LocalDateTime(2022, 06, 29), // summer period
|
||||||
|
LocalDateTime(2022, 01, 29), // winter period
|
||||||
|
};
|
||||||
|
for (const LocalDateTime& ldt : times) {
|
||||||
|
std::time_t t = ldt.timestamp().epochTime();
|
||||||
|
std::tm then;
|
||||||
|
then = *std::localtime(&t);
|
||||||
|
assertTrue (then.tm_gmtoff == ldt.tzd());
|
||||||
|
}
|
||||||
|
unsetenv("TZ");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LocalDateTimeTest::setUp()
|
void LocalDateTimeTest::setUp()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -479,6 +510,7 @@ CppUnit::Test* LocalDateTimeTest::suite()
|
|||||||
CppUnit_addTest(pSuite, LocalDateTimeTest, testArithmetics2);
|
CppUnit_addTest(pSuite, LocalDateTimeTest, testArithmetics2);
|
||||||
CppUnit_addTest(pSuite, LocalDateTimeTest, testSwap);
|
CppUnit_addTest(pSuite, LocalDateTimeTest, testSwap);
|
||||||
CppUnit_addTest(pSuite, LocalDateTimeTest, testTimezone);
|
CppUnit_addTest(pSuite, LocalDateTimeTest, testTimezone);
|
||||||
|
CppUnit_addTest(pSuite, LocalDateTimeTest, testTimezone2);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ public:
|
|||||||
void testArithmetics2();
|
void testArithmetics2();
|
||||||
void testSwap();
|
void testSwap();
|
||||||
void testTimezone();
|
void testTimezone();
|
||||||
|
void testTimezone2();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user