ISO8601
- Simplified and debugged ISO8601::resolve method regarding UTC, local and specified time offsets.
This commit is contained in:
148
src/ISO8601.cpp
148
src/ISO8601.cpp
@@ -603,6 +603,8 @@ bool ISO8601d::validate ()
|
|||||||
// long tm_gmtoff; offset from UTC in seconds
|
// long tm_gmtoff; offset from UTC in seconds
|
||||||
void ISO8601d::resolve ()
|
void ISO8601d::resolve ()
|
||||||
{
|
{
|
||||||
|
//std::cout << "# start ------------------------\n";
|
||||||
|
|
||||||
// Don't touch the original values.
|
// Don't touch the original values.
|
||||||
int year = _year;
|
int year = _year;
|
||||||
int month = _month;
|
int month = _month;
|
||||||
@@ -613,55 +615,69 @@ void ISO8601d::resolve ()
|
|||||||
int seconds = _seconds;
|
int seconds = _seconds;
|
||||||
int offset = _offset;
|
int offset = _offset;
|
||||||
bool utc = _utc;
|
bool utc = _utc;
|
||||||
|
//std::cout << "# input\n"
|
||||||
|
// << "# year=" << year << "\n"
|
||||||
|
// << "# month=" << month << "\n"
|
||||||
|
// << "# week=" << week << "\n"
|
||||||
|
// << "# weekday=" << weekday << "\n"
|
||||||
|
// << "# julian=" << julian << "\n"
|
||||||
|
// << "# day=" << day << "\n"
|
||||||
|
// << "# seconds=" << seconds << "\n"
|
||||||
|
// << "# offset=" << offset << "\n"
|
||||||
|
// << "# utc=" << utc << "\n";
|
||||||
|
|
||||||
struct tm t = {0};
|
// Get current time.
|
||||||
|
|
||||||
// Requests that mktime determine summer time effect.
|
|
||||||
t.tm_isdst = -1;
|
|
||||||
|
|
||||||
// Determine local time.
|
|
||||||
time_t now = time (NULL);
|
time_t now = time (NULL);
|
||||||
struct tm* local_now = localtime (&now);
|
//std::cout << "# now=" << now << "\n";
|
||||||
struct tm* utc_now = gmtime (&now);
|
|
||||||
|
|
||||||
// What is a complete TZ?
|
// A UTC offset needs to be accommodated. Once the offset is subtracted,
|
||||||
// utc
|
// only local and UTC times remain.
|
||||||
// offset
|
if (offset)
|
||||||
// local (get default)
|
|
||||||
if (utc)
|
|
||||||
offset = 0;
|
|
||||||
else if (! offset)
|
|
||||||
{
|
{
|
||||||
#ifdef HAVE_TM_GMTOFF
|
seconds -= offset;
|
||||||
offset = local_now->tm_gmtoff - (local_now->tm_isdst == 1 ? 3600 : 0);
|
now -= offset;
|
||||||
#else
|
utc = true;
|
||||||
// TODO Umm...
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subtract the offset, to project local to UTC.
|
// Get 'now' in the relevant location.
|
||||||
seconds -= offset;
|
struct tm* t_now = utc ? gmtime (&now) : localtime (&now);
|
||||||
|
//std::cout << "# t_now\n"
|
||||||
|
// << "# tm_year=" << t_now->tm_year << "\n"
|
||||||
|
// << "# tm_mon=" << t_now->tm_mon << "\n"
|
||||||
|
// << "# tm_mday=" << t_now->tm_mday << "\n"
|
||||||
|
// << "# tm_hour=" << t_now->tm_hour << "\n"
|
||||||
|
// << "# tm_min=" << t_now->tm_min << "\n"
|
||||||
|
// << "# tm_sec=" << t_now->tm_sec << "\n"
|
||||||
|
// << "# tm_isdst=" << t_now->tm_isdst << "\n";
|
||||||
|
|
||||||
// If the time is specified without a date, if it is earlier than 'now', then
|
int seconds_now = (t_now->tm_hour * 3600) +
|
||||||
// it refers to tomorrow.
|
(t_now->tm_min * 60) +
|
||||||
int seconds_utc_now = utc_now->tm_hour * 3600 +
|
t_now->tm_sec;
|
||||||
utc_now->tm_min * 60 +
|
//std::cout << "# seconds_now=" << seconds_now << "\n";
|
||||||
utc_now->tm_sec;
|
|
||||||
|
// Project forward one day if the specified seconds are earlier in the day
|
||||||
|
// than the current seconds.
|
||||||
if (year == 0 &&
|
if (year == 0 &&
|
||||||
month == 0 &&
|
month == 0 &&
|
||||||
day == 0 &&
|
day == 0 &&
|
||||||
week == 0 &&
|
week == 0 &&
|
||||||
weekday == 0 &&
|
weekday == 0 &&
|
||||||
seconds < seconds_utc_now)
|
seconds < seconds_now)
|
||||||
{
|
{
|
||||||
|
//std::cout << "# earlier today, therefore seconds += 86400\n"
|
||||||
|
// << "# seconds=" << seconds << "\n";
|
||||||
seconds += 86400;
|
seconds += 86400;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conversion of week + weekday to julian.
|
// Convert week + weekday --> julian.
|
||||||
if (week)
|
if (week)
|
||||||
{
|
{
|
||||||
julian = (week * 7) + weekday - dayOfWeek (year, 1, 4) - 3;
|
julian = (week * 7) + weekday - dayOfWeek (year, 1, 4) - 3;
|
||||||
|
//std::cout << "# week=" << week << " weekday=" << weekday << " specified\n"
|
||||||
|
// << "# julian=" << julian << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Provide default values for year, month, day.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Default values for year, month, day:
|
// Default values for year, month, day:
|
||||||
@@ -673,9 +689,9 @@ void ISO8601d::resolve ()
|
|||||||
//
|
//
|
||||||
if (year == 0)
|
if (year == 0)
|
||||||
{
|
{
|
||||||
year = local_now->tm_year + 1900;
|
year = t_now->tm_year + 1900;
|
||||||
month = local_now->tm_mon + 1;
|
month = t_now->tm_mon + 1;
|
||||||
day = local_now->tm_mday;
|
day = t_now->tm_mday;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -688,43 +704,75 @@ void ISO8601d::resolve ()
|
|||||||
day = 1;
|
day = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//std::cout << "# Applied default y m d\n"
|
||||||
|
// << "# year=" << year << "\n"
|
||||||
|
// << "# month=" << month << "\n"
|
||||||
|
// << "# day=" << day << "\n";
|
||||||
|
|
||||||
if (julian)
|
if (julian)
|
||||||
{
|
{
|
||||||
month = 1;
|
month = 1;
|
||||||
day = julian;
|
day = julian;
|
||||||
|
//std::cout << "# julian=" << julian << " specified\n"
|
||||||
|
// << "# month=" << month << "\n"
|
||||||
|
// << "# day=" << day << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct tm t = {0};
|
||||||
|
t.tm_isdst = -1; // Requests that mktime/gmtime determine summer time effect.
|
||||||
t.tm_year = year - 1900;
|
t.tm_year = year - 1900;
|
||||||
t.tm_mon = month - 1;
|
t.tm_mon = month - 1;
|
||||||
t.tm_mday = day;
|
t.tm_mday = day;
|
||||||
|
|
||||||
// What is a complete time spec?
|
if (seconds > 86400)
|
||||||
// seconds
|
|
||||||
if (seconds)
|
|
||||||
{
|
{
|
||||||
if (seconds > 86400)
|
//std::cout << "# seconds=" << seconds << " is more than a day\n";
|
||||||
{
|
int days = seconds / 86400;
|
||||||
int days = seconds / 86400;
|
t.tm_mday += days;
|
||||||
t.tm_mday += days;
|
seconds %= 86400;
|
||||||
seconds -= days * 86400;
|
//std::cout << "# t.tm_mday=" << t.tm_mday << "\n"
|
||||||
}
|
// << "# seconds=" << seconds << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
t.tm_hour = seconds / 3600;
|
t.tm_hour = seconds / 3600;
|
||||||
t.tm_min = (seconds % 3600) / 60;
|
t.tm_min = (seconds % 3600) / 60;
|
||||||
t.tm_sec = seconds % 60;
|
t.tm_sec = seconds % 60;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// User-provided default.
|
|
||||||
t.tm_hour = _default_seconds / 3600;
|
|
||||||
t.tm_min = (_default_seconds % 3600) / 60;
|
|
||||||
t.tm_sec = _default_seconds % 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
_value = timegm (&t);
|
//std::cout << "# Final t\n"
|
||||||
|
// << "# tm_year=" << t.tm_year << "\n"
|
||||||
|
// << "# tm_mon=" << t.tm_mon << "\n"
|
||||||
|
// << "# tm_mday=" << t.tm_mday << "\n"
|
||||||
|
// << "# tm_hour=" << t.tm_hour << "\n"
|
||||||
|
// << "# tm_min=" << t.tm_min << "\n"
|
||||||
|
// << "# tm_sec=" << t.tm_sec << "\n"
|
||||||
|
// << "# tm_isdst=" << t.tm_isdst << "\n";
|
||||||
|
|
||||||
|
_value = utc ? timegm (&t) : timelocal (&t);
|
||||||
|
//std::cout << "# _value " << _value << "\n";
|
||||||
|
|
||||||
|
//std::cout << "# end --------------------------\n";
|
||||||
|
//dump ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
void ISO8601d::dump ()
|
||||||
|
{
|
||||||
|
std::cout << "# Y=" << _year
|
||||||
|
<< " M=" << _month
|
||||||
|
<< " W=" << _week
|
||||||
|
<< " WD=" << _weekday
|
||||||
|
<< " J=" << _julian
|
||||||
|
<< " d=" << _day
|
||||||
|
<< " s=" << _seconds
|
||||||
|
<< " o=" << _offset
|
||||||
|
<< " Z=" << _utc
|
||||||
|
<< " ambi=" << _ambiguity
|
||||||
|
<< " --> " << _value
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
ISO8601p::ISO8601p ()
|
ISO8601p::ISO8601p ()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user