mirror of
https://github.com/pocoproject/poco.git
synced 2025-02-22 15:07:26 +01:00
#3509: fix dst and utcOffset handling for Dublin time zone
This commit is contained in:
parent
1b5de92f09
commit
6aa29ade17
@ -32,32 +32,44 @@ public:
|
|||||||
static int utcOffset();
|
static int utcOffset();
|
||||||
/// Returns the offset of local time to UTC, in seconds.
|
/// Returns the offset of local time to UTC, in seconds.
|
||||||
/// local time = UTC + utcOffset() + dst().
|
/// local time = UTC + utcOffset() + dst().
|
||||||
|
|
||||||
static int dst();
|
static int dst();
|
||||||
/// Returns the daylight saving time offset in seconds if
|
/// Returns the daylight saving time offset in seconds if
|
||||||
/// daylight saving time is in use.
|
/// daylight saving time is in use.
|
||||||
/// local time = UTC + utcOffset() + dst().
|
/// 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
|
||||||
/// platform this might only work reliably for certain
|
/// platform this might only work reliably for certain
|
||||||
/// date ranges, as the C library's localtime() function
|
/// date ranges, as the C library's localtime() function
|
||||||
/// is used.
|
/// is used.
|
||||||
|
|
||||||
static int tzd();
|
static int tzd();
|
||||||
/// Returns the time zone differential for the current timezone.
|
/// Returns the time zone differential for the current timezone.
|
||||||
/// The timezone differential is computed as utcOffset() + dst()
|
/// The timezone differential is computed as utcOffset() + dst()
|
||||||
/// and is expressed in seconds.
|
/// and is expressed in seconds.
|
||||||
|
|
||||||
static std::string name();
|
static std::string name();
|
||||||
/// Returns the timezone name currently in effect.
|
/// Returns the timezone name currently in effect.
|
||||||
|
|
||||||
static std::string standardName();
|
static std::string standardName();
|
||||||
/// Returns the timezone name if not daylight saving time is in effect.
|
/// Returns the timezone name if not daylight saving time is in effect.
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,34 +28,24 @@ public:
|
|||||||
{
|
{
|
||||||
tzset();
|
tzset();
|
||||||
}
|
}
|
||||||
|
|
||||||
int timeZone()
|
|
||||||
{
|
|
||||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined (__OpenBSD__) || POCO_OS == POCO_OS_ANDROID // no timezone global var
|
static long gmtOffset(const struct std::tm& t)
|
||||||
std::time_t now = std::time(NULL);
|
{
|
||||||
struct std::tm t;
|
#if defined(__CYGWIN__)
|
||||||
gmtime_r(&now, &t);
|
return t.__TM_GMTOFF;
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* name(bool dst)
|
const char* name(bool dst)
|
||||||
{
|
{
|
||||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||||
|
|
||||||
tzset();
|
tzset();
|
||||||
return tzname[dst ? 1 : 0];
|
return tzname[dst ? 1 : 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Poco::FastMutex _mutex;
|
Poco::FastMutex _mutex;
|
||||||
};
|
};
|
||||||
@ -64,19 +54,39 @@ private:
|
|||||||
static TZInfo tzInfo;
|
static TZInfo tzInfo;
|
||||||
|
|
||||||
|
|
||||||
int Timezone::utcOffset()
|
int Timezone::utcOffset(const Poco::Timestamp& timestamp)
|
||||||
{
|
{
|
||||||
return tzInfo.timeZone();
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -88,19 +98,19 @@ bool Timezone::isDst(const Timestamp& timestamp)
|
|||||||
return tms->tm_isdst > 0;
|
return tms->tm_isdst > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Timezone::name()
|
std::string Timezone::name()
|
||||||
{
|
{
|
||||||
return std::string(tzInfo.name(dst() != 0));
|
return std::string(tzInfo.name(dst() != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Timezone::standardName()
|
std::string Timezone::standardName()
|
||||||
{
|
{
|
||||||
return std::string(tzInfo.name(false));
|
return std::string(tzInfo.name(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Timezone::dstName()
|
std::string Timezone::dstName()
|
||||||
{
|
{
|
||||||
return std::string(tzInfo.name(true));
|
return std::string(tzInfo.name(true));
|
||||||
|
@ -65,7 +65,7 @@ void LocalDateTimeTest::testGregorian1()
|
|||||||
// the one on 1970-1-1
|
// the one on 1970-1-1
|
||||||
//assertTrue (dt.tzd() == Timezone::tzd());
|
//assertTrue (dt.tzd() == Timezone::tzd());
|
||||||
assertTrue (dt.julianDay() == 2440587.5);
|
assertTrue (dt.julianDay() == 2440587.5);
|
||||||
|
|
||||||
dt.assign(2001, 9, 9, 1, 46, 40);
|
dt.assign(2001, 9, 9, 1, 46, 40);
|
||||||
assertTrue (dt.year() == 2001);
|
assertTrue (dt.year() == 2001);
|
||||||
assertTrue (dt.month() == 9);
|
assertTrue (dt.month() == 9);
|
||||||
@ -92,7 +92,7 @@ void LocalDateTimeTest::testGregorian2()
|
|||||||
assertTrue (dt.millisecond() == 0);
|
assertTrue (dt.millisecond() == 0);
|
||||||
assertTrue (dt.dayOfWeek() == 4);
|
assertTrue (dt.dayOfWeek() == 4);
|
||||||
assertTrue (dt.tzd() == 2*3600);
|
assertTrue (dt.tzd() == 2*3600);
|
||||||
|
|
||||||
dt.assign(-7*3600, 2001, 9, 9, 1, 46, 40, 0, 0);
|
dt.assign(-7*3600, 2001, 9, 9, 1, 46, 40, 0, 0);
|
||||||
assertTrue (dt.year() == 2001);
|
assertTrue (dt.year() == 2001);
|
||||||
assertTrue (dt.month() == 9);
|
assertTrue (dt.month() == 9);
|
||||||
@ -134,12 +134,12 @@ void LocalDateTimeTest::testConversions()
|
|||||||
assertTrue (dt5.millisecond() == 234);
|
assertTrue (dt5.millisecond() == 234);
|
||||||
assertTrue (dt5.dayOfWeek() == 5);
|
assertTrue (dt5.dayOfWeek() == 5);
|
||||||
assertTrue (dt5.tzd() == -4*3600);
|
assertTrue (dt5.tzd() == -4*3600);
|
||||||
|
|
||||||
DateTime dt6(2005, 1, 28, 14, 24, 44, 234, 0);
|
DateTime dt6(2005, 1, 28, 14, 24, 44, 234, 0);
|
||||||
LocalDateTime dt7(3600, dt6);
|
LocalDateTime dt7(3600, dt6);
|
||||||
LocalDateTime dt8(3600, dt6, false);
|
LocalDateTime dt8(3600, dt6, false);
|
||||||
LocalDateTime dt9(3600, dt6, true);
|
LocalDateTime dt9(3600, dt6, true);
|
||||||
|
|
||||||
assertTrue (dt7.hour() == 15);
|
assertTrue (dt7.hour() == 15);
|
||||||
assertTrue (dt8.hour() == 14);
|
assertTrue (dt8.hour() == 14);
|
||||||
assertTrue (dt9.hour() == 15);
|
assertTrue (dt9.hour() == 15);
|
||||||
@ -169,9 +169,9 @@ void LocalDateTimeTest::testCalcs()
|
|||||||
assertTrue (dt1.week(DateTime::MONDAY) == 1);
|
assertTrue (dt1.week(DateTime::MONDAY) == 1);
|
||||||
dt1.assign(2007, 12, 31);
|
dt1.assign(2007, 12, 31);
|
||||||
assertTrue (dt1.week(DateTime::MONDAY) == 53);
|
assertTrue (dt1.week(DateTime::MONDAY) == 53);
|
||||||
|
|
||||||
// Jan 1 is Mon
|
// Jan 1 is Mon
|
||||||
dt1.assign(2001, 1, 1);
|
dt1.assign(2001, 1, 1);
|
||||||
assertTrue (dt1.week() == 1);
|
assertTrue (dt1.week() == 1);
|
||||||
dt1.assign(2001, 1, 7);
|
dt1.assign(2001, 1, 7);
|
||||||
assertTrue (dt1.week() == 1);
|
assertTrue (dt1.week() == 1);
|
||||||
@ -205,7 +205,7 @@ void LocalDateTimeTest::testCalcs()
|
|||||||
assertTrue (dt1.week() == 3);
|
assertTrue (dt1.week() == 3);
|
||||||
dt1.assign(2003, 1, 20);
|
dt1.assign(2003, 1, 20);
|
||||||
assertTrue (dt1.week() == 4);
|
assertTrue (dt1.week() == 4);
|
||||||
|
|
||||||
// Jan 1 is Thu
|
// Jan 1 is Thu
|
||||||
dt1.assign(2004, 1, 1);
|
dt1.assign(2004, 1, 1);
|
||||||
assertTrue (dt1.week() == 1);
|
assertTrue (dt1.week() == 1);
|
||||||
@ -241,7 +241,7 @@ void LocalDateTimeTest::testCalcs()
|
|||||||
assertTrue (dt1.week() == 2);
|
assertTrue (dt1.week() == 2);
|
||||||
dt1.assign(2000, 1, 17);
|
dt1.assign(2000, 1, 17);
|
||||||
assertTrue (dt1.week() == 3);
|
assertTrue (dt1.week() == 3);
|
||||||
|
|
||||||
// Jan 1 is Sun
|
// Jan 1 is Sun
|
||||||
dt1.assign(1995, 1, 1);
|
dt1.assign(1995, 1, 1);
|
||||||
assertTrue (dt1.week() == 0);
|
assertTrue (dt1.week() == 0);
|
||||||
@ -262,7 +262,7 @@ void LocalDateTimeTest::testAMPM()
|
|||||||
assertTrue (dt1.isAM());
|
assertTrue (dt1.isAM());
|
||||||
assertTrue (!dt1.isPM());
|
assertTrue (!dt1.isPM());
|
||||||
assertTrue (dt1.hourAMPM() == 12);
|
assertTrue (dt1.hourAMPM() == 12);
|
||||||
|
|
||||||
dt1.assign(2005, 1, 1, 12, 15, 30);
|
dt1.assign(2005, 1, 1, 12, 15, 30);
|
||||||
assertTrue (!dt1.isAM());
|
assertTrue (!dt1.isAM());
|
||||||
assertTrue (dt1.isPM());
|
assertTrue (dt1.isPM());
|
||||||
@ -280,14 +280,14 @@ void LocalDateTimeTest::testRelational1()
|
|||||||
LocalDateTime dt1(2005, 1, 1, 0, 15, 30);
|
LocalDateTime dt1(2005, 1, 1, 0, 15, 30);
|
||||||
LocalDateTime dt2(2005, 1, 2, 0, 15, 30);
|
LocalDateTime dt2(2005, 1, 2, 0, 15, 30);
|
||||||
LocalDateTime dt3(dt1);
|
LocalDateTime dt3(dt1);
|
||||||
|
|
||||||
assertTrue (dt1 < dt2);
|
assertTrue (dt1 < dt2);
|
||||||
assertTrue (dt1 <= dt2);
|
assertTrue (dt1 <= dt2);
|
||||||
assertTrue (dt2 > dt1);
|
assertTrue (dt2 > dt1);
|
||||||
assertTrue (dt2 >= dt1);
|
assertTrue (dt2 >= dt1);
|
||||||
assertTrue (dt1 != dt2);
|
assertTrue (dt1 != dt2);
|
||||||
assertTrue (!(dt1 == dt2));
|
assertTrue (!(dt1 == dt2));
|
||||||
|
|
||||||
assertTrue (dt1 == dt3);
|
assertTrue (dt1 == dt3);
|
||||||
assertTrue (!(dt1 != dt3));
|
assertTrue (!(dt1 != dt3));
|
||||||
assertTrue (dt1 >= dt3);
|
assertTrue (dt1 >= dt3);
|
||||||
@ -309,7 +309,7 @@ void LocalDateTimeTest::testRelational2()
|
|||||||
assertTrue (dt2 >= dt1);
|
assertTrue (dt2 >= dt1);
|
||||||
assertTrue (dt1 != dt2);
|
assertTrue (dt1 != dt2);
|
||||||
assertTrue (!(dt1 == dt2));
|
assertTrue (!(dt1 == dt2));
|
||||||
|
|
||||||
assertTrue (dt1 == dt3);
|
assertTrue (dt1 == dt3);
|
||||||
assertTrue (!(dt1 != dt3));
|
assertTrue (!(dt1 != dt3));
|
||||||
assertTrue (dt1 >= dt3);
|
assertTrue (dt1 >= dt3);
|
||||||
@ -323,13 +323,13 @@ void LocalDateTimeTest::testArithmetics1()
|
|||||||
{
|
{
|
||||||
LocalDateTime dt1(2005, 1, 1, 0, 15, 30);
|
LocalDateTime dt1(2005, 1, 1, 0, 15, 30);
|
||||||
LocalDateTime dt2(2005, 1, 2, 0, 15, 30);
|
LocalDateTime dt2(2005, 1, 2, 0, 15, 30);
|
||||||
|
|
||||||
Timespan s = dt2 - dt1;
|
Timespan s = dt2 - dt1;
|
||||||
assertTrue (s.days() == 1);
|
assertTrue (s.days() == 1);
|
||||||
|
|
||||||
LocalDateTime dt3 = dt1 + s;
|
LocalDateTime dt3 = dt1 + s;
|
||||||
assertTrue (dt3 == dt2);
|
assertTrue (dt3 == dt2);
|
||||||
|
|
||||||
dt3 -= s;
|
dt3 -= s;
|
||||||
assertTrue (dt3 == dt1);
|
assertTrue (dt3 == dt1);
|
||||||
dt1 += s;
|
dt1 += s;
|
||||||
@ -341,13 +341,13 @@ void LocalDateTimeTest::testArithmetics2()
|
|||||||
{
|
{
|
||||||
LocalDateTime dt1(2*3600, 2005, 1, 1, 15, 30, 0, 0, 0);
|
LocalDateTime dt1(2*3600, 2005, 1, 1, 15, 30, 0, 0, 0);
|
||||||
LocalDateTime dt2(5*3600, 2005, 1, 2, 18, 30, 0, 0, 0);
|
LocalDateTime dt2(5*3600, 2005, 1, 2, 18, 30, 0, 0, 0);
|
||||||
|
|
||||||
Timespan s = dt2 - dt1;
|
Timespan s = dt2 - dt1;
|
||||||
assertTrue (s.days() == 1);
|
assertTrue (s.days() == 1);
|
||||||
|
|
||||||
LocalDateTime dt3 = dt1 + s;
|
LocalDateTime dt3 = dt1 + s;
|
||||||
assertTrue (dt3 == dt2);
|
assertTrue (dt3 == dt2);
|
||||||
|
|
||||||
dt3 -= s;
|
dt3 -= s;
|
||||||
assertTrue (dt3 == dt1);
|
assertTrue (dt3 == dt1);
|
||||||
dt1 += s;
|
dt1 += s;
|
||||||
@ -359,7 +359,7 @@ void LocalDateTimeTest::testSwap()
|
|||||||
{
|
{
|
||||||
LocalDateTime dt1(2005, 1, 1, 0, 15, 30);
|
LocalDateTime dt1(2005, 1, 1, 0, 15, 30);
|
||||||
LocalDateTime dt2(2005, 1, 2, 0, 15, 30);
|
LocalDateTime dt2(2005, 1, 2, 0, 15, 30);
|
||||||
|
|
||||||
assertTrue (dt1 < dt2);
|
assertTrue (dt1 < dt2);
|
||||||
dt1.swap(dt2);
|
dt1.swap(dt2);
|
||||||
assertTrue (dt2 < dt1);
|
assertTrue (dt2 < dt1);
|
||||||
@ -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