mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-30 21:50:47 +01:00
* Foundation/include/Poco/LocalDateTime.h
* Foundation/src/LocalDateTime.cpp
- Fixed Sourceforge tracker 1800031.
The time zone differential was not being maintained in many places.
There are some minor functionality changes with this changeset however.
* Assignment methods which do not take the full time information or a
tzd as parameters will adjust the time stamp for DST according to
the time specified. The only methods that do not fall under this
constraint are:
- constructors or assigns which accept year, month, day, etc.
- constructors or assigns which accept a tzd
* operators += and -= correctly adjust for DST boundary crossings.
* operators + and - will return a LocalDateTime instance that has
been adjust for DST boundary crossings.
* Foundation/testsuite/src/LocalDateTimeTest.h
* Foundation/testsuite/src/LocalDateTimeTest.cpp
- Added testTimezone method.
- Removed an assertion in testGregorian1() that would fail when the
current DST offset differed from that of 1970-1-1.
This commit is contained in:
@@ -29,8 +29,11 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
#include "LocalDateTimeTest.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
|
||||
#include "CppUnit/TestCaller.h"
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/LocalDateTime.h"
|
||||
@@ -39,6 +42,8 @@
|
||||
#include "Poco/Timespan.h"
|
||||
#include "Poco/Timezone.h"
|
||||
|
||||
#include "Poco/DateTimeFormat.h"
|
||||
#include "Poco/DateTimeFormatter.h"
|
||||
|
||||
using Poco::LocalDateTime;
|
||||
using Poco::DateTime;
|
||||
@@ -68,7 +73,9 @@ void LocalDateTimeTest::testGregorian1()
|
||||
assert (dt.second() == 0);
|
||||
assert (dt.millisecond() == 0);
|
||||
assert (dt.dayOfWeek() == 4);
|
||||
assert (dt.tzd() == Timezone::tzd());
|
||||
// REMOVED: this fails when the current DST offset differs from
|
||||
// the one on 1970-1-1
|
||||
//assert (dt.tzd() == Timezone::tzd());
|
||||
assert (dt.julianDay() == 2440587.5);
|
||||
|
||||
dt.assign(2001, 9, 9, 1, 46, 40);
|
||||
@@ -371,6 +378,93 @@ void LocalDateTimeTest::testSwap()
|
||||
}
|
||||
|
||||
|
||||
void LocalDateTimeTest::testTimezone()
|
||||
{
|
||||
std::time_t tINCREMENT = (30 * 24 * 60 * 60); // 30 days
|
||||
Timespan tsINCREMENT(30*Timespan::DAYS);
|
||||
LocalDateTime now;
|
||||
std::time_t t = std::time(NULL);
|
||||
std::tm then;
|
||||
bool foundDST = false;
|
||||
|
||||
then = *std::localtime(&t);
|
||||
if (then.tm_isdst >= 0)
|
||||
{
|
||||
std::string tzNow, tzThen;
|
||||
char tzBuf[12];
|
||||
int iterations = 0;
|
||||
std::strftime(&tzBuf[0], sizeof(tzBuf), "%z", &then);
|
||||
tzNow = tzThen = tzBuf;
|
||||
while (iterations < 14)
|
||||
{
|
||||
// Add one month until the timezone changes or we roll
|
||||
// over 13 months.
|
||||
t += tINCREMENT;
|
||||
then = *std::localtime(&t);
|
||||
std::strftime(&tzBuf[0], sizeof(tzBuf), "%z", &then);
|
||||
tzThen = tzBuf;
|
||||
foundDST = (tzNow == tzThen);
|
||||
if (foundDST)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++iterations;
|
||||
}
|
||||
if (foundDST)
|
||||
{
|
||||
// We found a timezone change that was induced by changing
|
||||
// the month, so we crossed a DST boundary. Now we can
|
||||
// actually do the test...
|
||||
//
|
||||
// Start with the current time and add 30 days for 13
|
||||
// iterations. Do this with both a LocalDateTime object and
|
||||
// a ANSI C time_t. Then create a LocalDateTime based on the
|
||||
// time_t and verify that the time_t calculated value is equal
|
||||
// to the LocalDateTime value. The comparision operator
|
||||
// verifies the _dateTime and _tzd members.
|
||||
LocalDateTime dt2;
|
||||
t = std::time(NULL);
|
||||
for (iterations = 0; iterations < 14; ++iterations)
|
||||
{
|
||||
t += tINCREMENT;
|
||||
dt2 += tsINCREMENT;
|
||||
then = *std::localtime(&t);
|
||||
|
||||
// This is the tricky part. We have to use the constructor
|
||||
// from a UTC DateTime object that is constructed from the
|
||||
// time_t. The LocalDateTime constructor with integer
|
||||
// arguments, LocalDateTime(yr, mon, day, ...), assumes that
|
||||
// the time is already adjusted with respect to the time
|
||||
// zone. The DateTime conversion constructor, however, does
|
||||
// not. So we want to construct from the UTC time.
|
||||
//
|
||||
// The second tricky part is that we want to use the
|
||||
// sub-second information from the LocalDateTime object
|
||||
// since ANSI C time routines are not sub-second accurate.
|
||||
then = *std::gmtime(&t);
|
||||
LocalDateTime calcd(DateTime((then.tm_year + 1900),
|
||||
(then.tm_mon + 1),
|
||||
then.tm_mday,
|
||||
then.tm_hour,
|
||||
then.tm_min,
|
||||
then.tm_sec,
|
||||
dt2.millisecond(),
|
||||
dt2.microsecond()));
|
||||
assert (dt2 == calcd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundDST)
|
||||
{
|
||||
std::cerr
|
||||
<< __FILE__ << ":" << __LINE__
|
||||
<< " - failed to locate DST boundary, timezone test skipped."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LocalDateTimeTest::setUp()
|
||||
{
|
||||
}
|
||||
@@ -395,6 +489,7 @@ CppUnit::Test* LocalDateTimeTest::suite()
|
||||
CppUnit_addTest(pSuite, LocalDateTimeTest, testArithmetics1);
|
||||
CppUnit_addTest(pSuite, LocalDateTimeTest, testArithmetics2);
|
||||
CppUnit_addTest(pSuite, LocalDateTimeTest, testSwap);
|
||||
CppUnit_addTest(pSuite, LocalDateTimeTest, testTimezone);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user