- Merged libexpr ISO8601 code.
This commit is contained in:
Paul Beckingham 2014-01-02 00:45:16 -05:00
parent 4cf0763845
commit 712b0bb4b5
6 changed files with 1429 additions and 1 deletions

View file

@ -18,6 +18,7 @@ set (task_SRCS A3.cpp A3.h
E9.cpp E9.h E9.cpp E9.h
File.cpp File.h File.cpp File.h
Hooks.cpp Hooks.h Hooks.cpp Hooks.h
ISO8601.cpp ISO8601.h
JSON.cpp JSON.h JSON.cpp JSON.h
LRParser.cpp LRParser.h LRParser.cpp LRParser.h
Msg.cpp Msg.h Msg.cpp Msg.h

880
src/ISO8601.cpp Normal file
View file

@ -0,0 +1,880 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#include <cmake.h>
#include <ISO8601.h>
////////////////////////////////////////////////////////////////////////////////
ISO8601d::ISO8601d ()
{
clear ();
}
////////////////////////////////////////////////////////////////////////////////
ISO8601d::~ISO8601d ()
{
}
////////////////////////////////////////////////////////////////////////////////
ISO8601d::operator time_t () const
{
return _value;
}
////////////////////////////////////////////////////////////////////////////////
// By default, ISO8601d allows ambiguous dates, such as YYYY, YYYYMMDD, HHMMSS.
// These are also valid numbers. Setting ambiguity to false inhibites the
// parsing of these as dates.
void ISO8601d::ambiguity (bool value)
{
_ambiguity = value;
}
////////////////////////////////////////////////////////////////////////////////
// Supported:
//
// result ::= date-ext 'T' time-ext 'Z' # UTC
// | date-ext 'T' time-ext offset-ext # Specified TZ
// | date-ext 'T' time-ext # Local
// | date-ext # Local
// | date 'T' time 'Z'
// | date 'T' time offset-ext
// | date 'T' time
// | date
// | time-ext 'Z'
// | time-ext offset-ext
// | time-ext
// | time 'Z'
// | time offset
// | time
// ;
//
// date-ext ::= ±YYYYY-MM-DD Νot needed
// | ±YYYYY-Www-D Νot needed
// | ±YYYYY-Www Νot needed
// | ±YYYYY-DDD Νot needed
// | YYYY-MM-DD
// | YYYY-DDD
// | YYYY-Www-D
// | YYYY-Www
// ;
//
// date ::= ±YYYYYMMDD Νot needed
// | ±YYYYYWwwD Νot needed
// | ±YYYYYWww Νot needed
// | ±YYYYYDDD Νot needed
// | ±YYYYYMM Νot needed
// | ±YYYYY Νot needed
// | ±YYY Νot needed
// | YYYYMMDD Ambiguous (number)
// | YYYYWwwD
// | YYYYWww
// | YYYYDDD Ambiguous (number)
// | YYYY-MM
// | YYYY Ambiguous (number)
// | YY Ambiguous (number)
// ;
//
// time-ext ::= hh:mm:ss[,ss]
// | hh:mm[,mm]
// | hh[,hh] Ambiguous (number)
// ;
//
// time ::= hhmmss[,ss] Ambiguous (number)
// | hhmm[,mm] Ambiguous (number)
// | hh[,hh] Ambiguous (number)
// ;
//
// time-utc-ext ::= hh:mm[:ss] 'Z' ;
// time-utc ::= hh[mm[ss]] 'Z' ;
//
// offset-ext ::= ±hh[:mm] ;
// offset ::= ±hh[mm] ;
//
// Not yet supported:
//
// recurrence ::=
// | 'R' [n] '/' designated '/' datetime-ext # duration end
// | 'R' [n] '/' designated '/' datetime # duration end
// | 'R' [n] '/' designated # duration
// | 'R' [n] '/' datetime-ext '/' designated # start duration
// | 'R' [n] '/' datetime-ext '/' datetime-ext # start end
// | 'R' [n] '/' datetime '/' designated # start duration
// | 'R' [n] '/' datetime '/' datetime # start end
// ;
//
bool ISO8601d::parse (const std::string& input, std::string::size_type& start)
{
std::string::size_type i = start;
Nibbler n (input.substr (i));
if (parse_date_time_ext (n) || // Most complex first.
parse_date_ext (n) ||
parse_time_utc_ext (n) ||
parse_time_off_ext (n) ||
parse_date_time (n) ||
parse_date (n, _ambiguity) ||
parse_time_utc (n) ||
parse_time_off (n) ||
parse_time_ext (n) || // Time last, as it is the most permissive.
parse_time (n, _ambiguity))
{
// Check the values and determine time_t.
if (validate ())
{
// Record cursor position.
start = n.cursor ();
resolve ();
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
void ISO8601d::clear ()
{
_ambiguity = true;
_year = 0;
_month = 0;
_week = 0;
_weekday = 0;
_julian = 0;
_day = 0;
_seconds = 0;
_offset = 0;
_utc = false;
_value = 0;
_default_seconds = 0;
}
////////////////////////////////////////////////////////////////////////////////
void ISO8601d::set_default_time (int hours, int minutes, int seconds)
{
_default_seconds = (hours * 3600) + (minutes * 60) + seconds;
}
////////////////////////////////////////////////////////////////////////////////
// date-ext 'T' time-ext 'Z'
// date-ext 'T' time-ext offset-ext
// date-ext 'T' time-ext
bool ISO8601d::parse_date_time_ext (Nibbler& n)
{
n.save ();
if (parse_date_ext (n))
{
if (n.skip ('T') &&
parse_time_ext (n))
{
if (n.skip ('Z'))
_utc = true;
else if (parse_off_ext (n))
;
if (! isdigit (n.next ()))
return true;
}
// Restore date_ext
_year = 0;
_month = 0;
_week = 0;
_weekday = 0;
_julian = 0;
_day = 0;
}
n.restore ();
return false;
}
////////////////////////////////////////////////////////////////////////////////
// date 'T' time 'Z'
// date 'T' time offset
// date 'T' time
bool ISO8601d::parse_date_time (Nibbler& n)
{
Nibbler backup (n);
if (parse_date (n, true))
{
if (n.skip ('T') &&
parse_time (n, true))
{
if (n.skip ('Z'))
{
_utc = true;
if (!isdigit (n.next ()))
return true;
}
else if (parse_off (n))
{
if (!isdigit (n.next ()))
return true;
}
if (!isdigit (n.next ()))
return true;
}
// Restore date
_year = 0;
_month = 0;
_week = 0;
_weekday = 0;
_julian = 0;
_day = 0;
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// YYYY-MM-DD
// YYYY-DDD
// YYYY-Www-D
// YYYY-Www
bool ISO8601d::parse_date_ext (Nibbler& n)
{
Nibbler backup (n);
int year;
if (n.getDigit4 (year) &&
n.skip ('-'))
{
int month;
int day;
if (n.skip ('W') &&
n.getDigit2 (_week))
{
if (n.skip ('-') &&
n.getDigit (_weekday))
{
}
_year = year;
if (!isdigit (n.next ()))
return true;
}
else if (n.getDigit3 (_julian))
{
_year = year;
if (!isdigit (n.next ()))
return true;
}
else if (n.getDigit2 (month) &&
n.skip ('-') &&
n.getDigit2 (day))
{
_year = year;
_month = month;
_day = day;
if (!isdigit (n.next ()))
return true;
}
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// YYYYMMDD Ambiguous (number)
// YYYYWwwD
// YYYYWww
// YYYYDDD Ambiguous (number)
// YYYY-MM
bool ISO8601d::parse_date (Nibbler& n, bool ambiguous)
{
Nibbler backup (n);
int year;
if (n.getDigit4 (year))
{
int month;
if (n.skip ('W'))
{
int week;
if (n.getDigit2 (week))
{
_week = week;
int day;
if (n.getDigit (day))
_weekday = day;
_year = year;
if (!isdigit (n.next ()))
return true;
}
}
else if (n.skip ('-'))
{
if (n.getDigit2 (_month))
{
_year = year;
if (!isdigit (n.next ()))
return true;
}
}
else if (n.getDigit4 (month))
{
_year = year;
_month = month / 100;
_day = month % 100;
if (!isdigit (n.next ()))
return true;
}
else if (ambiguous && n.getDigit3 (_julian))
{
_year = year;
if (!isdigit (n.next ()))
return true;
}
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// ±hh[:mm]
bool ISO8601d::parse_off_ext (Nibbler& n)
{
Nibbler backup (n);
std::string sign;
if (n.getN (1, sign))
{
if (sign == "+" || sign == "-")
{
int offset;
int hh;
int mm;
if (n.getDigit2 (hh) &&
!n.getDigit (mm))
{
offset = hh * 3600;
if (n.skip (':') &&
n.getDigit2 (mm))
offset += mm * 60;
_offset = (sign == "-") ? -offset : offset;
if (!isdigit (n.next ()))
return true;
}
}
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// ±hh[mm]
bool ISO8601d::parse_off (Nibbler& n)
{
Nibbler backup (n);
std::string sign;
if (n.getN (1, sign))
{
if (sign == "+" || sign == "-")
{
int offset;
int hh;
if (n.getDigit2 (hh))
{
offset = hh * 3600;
int mm;
if (n.getDigit2 (mm))
offset += mm * 60;
_offset = (sign == "-") ? -offset : offset;
if (!isdigit (n.next ()))
return true;
}
}
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// hh[:mm[:ss]]
bool ISO8601d::parse_time_ext (Nibbler& n)
{
Nibbler backup (n);
int seconds = 0;
int hh;
int mm;
int ss;
if (n.getDigit2 (hh) &&
!n.getDigit (mm))
{
seconds = hh * 3600;
if (n.skip (':') &&
n.getDigit2 (mm) &&
!n.getDigit (ss))
{
seconds += mm * 60;
if (n.skip (':') &&
n.getDigit2 (ss))
seconds += ss;
_seconds = seconds;
return true;
}
if (_ambiguity)
{
_seconds = seconds;
if (!isdigit (n.next ()))
return true;
}
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// hh[mm[ss]]
bool ISO8601d::parse_time (Nibbler& n, bool ambiguous)
{
if (!ambiguous)
return false;
Nibbler backup (n);
int seconds = 0;
int hh;
if (n.getDigit2 (hh))
{
seconds = hh * 3600;
int mm;
if (n.getDigit2 (mm))
{
seconds += mm * 60;
int ss;
if (n.getDigit2 (ss))
seconds += ss;
}
_seconds = seconds;
if (!isdigit (n.next ()))
return true;
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// time-ext 'Z'
bool ISO8601d::parse_time_utc_ext (Nibbler& n)
{
n.save ();
if (parse_time_ext (n) &&
n.skip ('Z'))
{
_utc = true;
if (!isdigit (n.next ()))
return true;
}
n.restore ();
return false;
}
////////////////////////////////////////////////////////////////////////////////
// time 'Z'
bool ISO8601d::parse_time_utc (Nibbler& n)
{
n.save ();
if (parse_time (n, true) &&
n.skip ('Z'))
{
_utc = true;
if (!isdigit (n.next ()))
return true;
}
n.restore ();
return false;
}
////////////////////////////////////////////////////////////////////////////////
// time-ext offset-ext
bool ISO8601d::parse_time_off_ext (Nibbler& n)
{
Nibbler backup (n);
if (parse_time_ext (n) &&
parse_off_ext (n))
{
if (!isdigit (n.next ()))
return true;
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// time offset
bool ISO8601d::parse_time_off (Nibbler& n)
{
Nibbler backup (n);
if (parse_time (n, true) &&
parse_off (n))
{
if (!isdigit (n.next ()))
return true;
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// Using Zeller's Congruence.
int ISO8601d::dayOfWeek (int year, int month, int day)
{
int adj = (14 - month) / 12;
int m = month + 12 * adj - 2;
int y = year - adj;
return (day + (13 * m - 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;
}
////////////////////////////////////////////////////////////////////////////////
// Validation via simple range checking.
bool ISO8601d::validate ()
{
// _year;
if ((_year && (_year < 1900 || _year > 2100)) ||
(_month && (_month < 1 || _month > 12)) ||
(_week && (_week < 1 || _week > 53)) ||
(_weekday && (_weekday < 0 || _weekday > 6)) ||
(_julian && (_julian < 0 || _julian > 366)) ||
(_day && (_day < 1 || _day > 31)) ||
(_seconds && (_seconds < 1 || _seconds > 86400)) ||
(_offset && (_offset < -86400 || _offset > 86400)))
return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
// int tm_sec; seconds (0 - 60)
// int tm_min; minutes (0 - 59)
// int tm_hour; hours (0 - 23)
// int tm_mday; day of month (1 - 31)
// int tm_mon; month of year (0 - 11)
// int tm_year; year - 1900
// int tm_wday; day of week (Sunday = 0)
// int tm_yday; day of year (0 - 365)
// int tm_isdst; is summer time in effect?
// char *tm_zone; abbreviation of timezone name
// long tm_gmtoff; offset from UTC in seconds
void ISO8601d::resolve ()
{
// Don't touch the original values.
int year = _year;
int month = _month;
int week = _week;
int weekday = _weekday;
int julian = _julian;
int day = _day;
int seconds = _seconds;
int offset = _offset;
bool utc = _utc;
struct tm t = {0};
// Requests that mktime determine summer time effect.
t.tm_isdst = -1;
// Determine local time.
time_t now = time (NULL);
struct tm* local_now = localtime (&now);
struct tm* utc_now = gmtime (&now);
// What is a complete TZ?
// utc
// offset
// local (get default)
if (utc)
offset = 0;
else if (! offset)
{
#ifdef HAVE_TM_GMTOFF
offset = local_now->tm_gmtoff;
#else
// TODO Umm...
#endif
}
// Subtract the offset, to project local to UTC.
seconds -= offset;
// If the time is specified without a date, if it is earlier than 'now', then
// it refers to tomorrow.
int seconds_utc_now = utc_now->tm_hour * 3600 +
utc_now->tm_min * 60 +
utc_now->tm_sec;
if (year == 0 &&
month == 0 &&
day == 0 &&
week == 0 &&
weekday == 0 &&
seconds < seconds_utc_now)
{
seconds += 86400;
}
// Conversion of week + weekday to julian.
if (week)
{
julian = (week * 7) + weekday - dayOfWeek (year, 1, 4) - 3;
}
else
{
// Default values for year, month, day:
//
// y m d --> y m d
// y m - --> y m 1
// y - - --> y 1 1
// - - - --> now now now
//
if (year == 0)
{
year = local_now->tm_year + 1900;
month = local_now->tm_mon + 1;
day = local_now->tm_mday;
}
else
{
if (month == 0)
{
month = 1;
day = 1;
}
else if (day == 0)
day = 1;
}
}
if (julian)
{
month = 1;
day = julian;
}
t.tm_year = year - 1900;
t.tm_mon = month - 1;
t.tm_mday = day;
// What is a complete time spec?
// seconds
if (seconds)
{
if (seconds > 86400)
{
int days = seconds / 86400;
t.tm_mday += days;
seconds -= days * 86400;
}
t.tm_hour = seconds / 3600;
t.tm_min = (seconds % 3600) / 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);
}
////////////////////////////////////////////////////////////////////////////////
ISO8601p::ISO8601p ()
{
clear ();
}
////////////////////////////////////////////////////////////////////////////////
ISO8601p::~ISO8601p ()
{
}
////////////////////////////////////////////////////////////////////////////////
ISO8601p::operator time_t () const
{
return _value;
}
////////////////////////////////////////////////////////////////////////////////
// Supported:
//
// duration ::= designated # duration
//
// designated ::= 'P' [nn 'Y'] [nn 'M'] [nn 'D'] ['T' [nn 'H'] [nn 'M'] [nn 'S']]
//
// Not supported:
//
// duration ::= designated '/' datetime-ext # duration end
// | degignated '/' datetime # duration end
// | designated # duration
// | 'P' datetime-ext '/' datetime-ext # start end
// | 'P' datetime '/' datetime # start end
// | 'P' datetime-ext # start
// | 'P' datetime # start
// | datetime-ext '/' designated # start duration
// | datetime-ext '/' 'P' datetime-ext # start end
// | datetime-ext '/' datetime-ext # start end
// | datetime '/' designated # start duration
// | datetime '/' 'P' datetime # start end
// | datetime '/' datetime # start end
// ;
//
bool ISO8601p::parse (const std::string& input, std::string::size_type& start)
{
std::string::size_type i = start;
Nibbler n (input.substr (i));
if (parse_designated (n))
{
// Check the values and determine time_t.
if (validate ())
{
// Record cursor position.
start = n.cursor ();
resolve ();
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
void ISO8601p::clear ()
{
_year = 0;
_month = 0;
_day = 0;
_hours = 0;
_minutes = 0;
_seconds = 0;
_value = 0;
}
////////////////////////////////////////////////////////////////////////////////
// 'P' [nn 'Y'] [nn 'M'] [nn 'D'] ['T' [nn 'H'] [nn 'M'] [nn 'S']]
bool ISO8601p::parse_designated (Nibbler& n)
{
Nibbler backup (n);
if (n.skip ('P'))
{
int value;
n.save ();
if (n.getUnsignedInt (value) && n.skip ('Y'))
_year = value;
else
n.restore ();
n.save ();
if (n.getUnsignedInt (value) && n.skip ('M'))
_month = value;
else
n.restore ();
n.save ();
if (n.getUnsignedInt (value) && n.skip ('D'))
_day = value;
else
n.restore ();
if (n.skip ('T'))
{
n.save ();
if (n.getUnsignedInt (value) && n.skip ('H'))
_hours = value;
else
n.restore ();
n.save ();
if (n.getUnsignedInt (value) && n.skip ('M'))
_minutes = value;
else
n.restore ();
n.save ();
if (n.getUnsignedInt (value) && n.skip ('S'))
_seconds = value;
else
n.restore ();
}
return true;
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool ISO8601p::validate ()
{
return _year ||
_month ||
_day ||
_hours ||
_minutes ||
_seconds;
}
////////////////////////////////////////////////////////////////////////////////
// Allow un-normalized values.
void ISO8601p::resolve ()
{
_value = (_year * 365 * 86400) +
(_month * 30 * 86400) +
(_day * 86400) +
(_hours * 3600) +
(_minutes * 60) +
_seconds;
}
////////////////////////////////////////////////////////////////////////////////

110
src/ISO8601.h Normal file
View file

@ -0,0 +1,110 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_ISO8601
#define INCLUDED_ISO8601
#include <Nibbler.h>
#include <time.h>
// Date
class ISO8601d
{
public:
ISO8601d ();
~ISO8601d ();
ISO8601d (const ISO8601d&); // Unimplemented
ISO8601d& operator= (const ISO8601d&); // Unimplemented
operator time_t () const;
void ambiguity (bool);
bool parse (const std::string&, std::string::size_type&);
void clear ();
void set_default_time (int, int, int);
private:
bool parse_date_time_ext (Nibbler&);
bool parse_date_time (Nibbler&);
bool parse_date_ext (Nibbler&);
bool parse_date (Nibbler&, bool);
bool parse_off_ext (Nibbler&);
bool parse_off (Nibbler&);
bool parse_time_ext (Nibbler&);
bool parse_time (Nibbler&, bool);
bool parse_time_utc_ext (Nibbler&);
bool parse_time_utc (Nibbler&);
bool parse_time_off_ext (Nibbler&);
bool parse_time_off (Nibbler&);
int dayOfWeek (int, int, int);
bool validate ();
void resolve ();
public:
bool _ambiguity;
int _year;
int _month;
int _week;
int _weekday;
int _julian;
int _day;
int _seconds;
int _offset;
bool _utc;
time_t _value;
int _default_seconds;
};
// Period
class ISO8601p
{
public:
ISO8601p ();
~ISO8601p ();
ISO8601p (const ISO8601p&); // Unimplemented
ISO8601p& operator= (const ISO8601p&); // Unimplemented
operator time_t () const;
bool parse (const std::string&, std::string::size_type&);
void clear ();
private:
bool parse_designated (Nibbler&);
bool validate ();
void resolve ();
public:
int _year;
int _month;
int _day;
int _hours;
int _minutes;
int _seconds;
time_t _value;
};
// TODO Recurrence
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -9,7 +9,7 @@ include_directories (${CMAKE_SOURCE_DIR}
set (test_SRCS autocomplete.t color.t config.t date.t directory.t dom.t set (test_SRCS autocomplete.t color.t config.t date.t directory.t dom.t
duration.t file.t i18n.t json.t list.t msg.t nibbler.t path.t duration.t file.t i18n.t json.t list.t msg.t nibbler.t path.t
rx.t t.t t2.t taskmod.t tdb2.t text.t tree.t uri.t utf8.t util.t rx.t t.t t2.t taskmod.t tdb2.t text.t tree.t uri.t utf8.t util.t
view.t width.t json_test) view.t width.t json_test iso8601d.t iso8601p.t)
message ("-- Configuring run_all") message ("-- Configuring run_all")
if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})

315
test/iso8601d.t.cpp Normal file
View file

@ -0,0 +1,315 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2013 - 2014, Göteborg Bit Factory.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#include <cmake.h>
#include <iostream>
#include <time.h>
#include <test.h>
#include <ISO8601.h>
#include <Context.h>
Context context;
#define AMBIGUOUS // Include ambiguous forms
#undef AMBIGUOUS // Exclude ambiguous forms
////////////////////////////////////////////////////////////////////////////////
void testParse (
UnitTest& t,
const std::string& input,
int in_start,
int in_year,
int in_month,
int in_week,
int in_weekday,
int in_julian,
int in_day,
int in_seconds,
int in_offset,
bool in_utc,
time_t in_value)
{
std::string label = std::string ("parse (\"") + input + "\") --> ";
ISO8601d iso;
std::string::size_type start = 0;
t.ok (iso.parse (input, start), label + "true");
t.is ((int) start, in_start, label + "[]");
t.is (iso._year, in_year, label + "_year");
t.is (iso._month, in_month, label + "_month");
t.is (iso._week, in_week, label + "_week");
t.is (iso._weekday, in_weekday, label + "_weekday");
t.is (iso._julian, in_julian, label + "_julian");
t.is (iso._day, in_day, label + "_day");
t.is (iso._seconds, in_seconds, label + "_seconds");
t.is (iso._offset, in_offset, label + "_offset");
t.is (iso._utc, in_utc, label + "_utc");
t.is ((size_t) iso._value, (size_t) in_value, label + "_value");
}
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
UnitTest t (1610
#ifdef AMBIGUOUS
+ 48
#endif
);
ISO8601d iso;
std::string::size_type start = 0;
t.notok (iso.parse ("foo", start), "foo --> false");
t.is ((int)start, 0, "foo[0]");
// Determine local and UTC time.
time_t now = time (NULL);
struct tm* local_now = localtime (&now);
int local_s = (local_now->tm_hour * 3600) +
(local_now->tm_min * 60) +
local_now->tm_sec;
local_now->tm_hour = 0;
local_now->tm_min = 0;
local_now->tm_sec = 0;
time_t local = timelocal (local_now);
std::cout << "# local midnight today " << local << "\n";
local_now->tm_year = 2013 - 1900;
local_now->tm_mon = 12 - 1;
local_now->tm_mday = 6;
time_t local6 = timelocal (local_now);
std::cout << "# local midnight 2013-12-06 " << local6 << "\n";
local_now->tm_year = 2013 - 1900;
local_now->tm_mon = 12 - 1;
local_now->tm_mday = 1;
time_t local1 = timelocal (local_now);
std::cout << "# local midnight 2013-12-01 " << local1 << "\n";
struct tm* utc_now = gmtime (&now);
int utc_s = (utc_now->tm_hour * 3600) +
(utc_now->tm_min * 60) +
utc_now->tm_sec;
utc_now->tm_hour = 0;
utc_now->tm_min = 0;
utc_now->tm_sec = 0;
time_t utc = timegm (utc_now);
std::cout << "# utc midnight today " << utc << "\n";
utc_now->tm_year = 2013 - 1900;
utc_now->tm_mon = 12 - 1;
utc_now->tm_mday = 6;
time_t utc6 = timegm (utc_now);
std::cout << "# utc midnight 2013-12-06 " << utc6 << "\n";
utc_now->tm_year = 2013 - 1900;
utc_now->tm_mon = 12 - 1;
utc_now->tm_mday = 1;
time_t utc1 = timegm (utc_now);
std::cout << "# utc midnight 2013-12-01 " << utc1 << "\n";
int hms = (12 * 3600) + (34 * 60) + 56; // The time 12:34:56 in seconds.
int hm = (12 * 3600) + (34 * 60); // The time 12:34:00 in seconds.
int h = (12 * 3600); // The time 12:00:00 in seconds.
int z = 3600; // TZ offset.
int ld = local_s > hms ? 86400 : 0; // Local extra day if now > hms.
int ud = utc_s > hms ? 86400 : 0; // UTC extra day if now > hms.
std::cout << "# ld " << ld << "\n";
std::cout << "# ud " << ud << "\n";
// Aggregated.
// input i Year Mo Wk WD Jul Da Secs TZ UTC time_t
testParse (t, "12:34:56 ", 8, 0, 0, 0, 0, 0, 0, hms, 0, false, local+hms+ld );
// time-ext
// input i Year Mo Wk WD Jul Da Secs TZ UTC time_t
testParse (t, "12:34:56Z", 9, 0, 0, 0, 0, 0, 0, hms, 0, true, utc+hms+ud );
testParse (t, "12:34Z", 6, 0, 0, 0, 0, 0, 0, hm, 0, true, utc+hm+ud );
testParse (t, "12Z", 3, 0, 0, 0, 0, 0, 0, h, 0, true, utc+h+ud );
testParse (t, "12:34:56+01:00", 14, 0, 0, 0, 0, 0, 0, hms, 3600, false, utc+hms-z+ud );
testParse (t, "12:34:56+01", 11, 0, 0, 0, 0, 0, 0, hms, 3600, false, utc+hms-z+ud );
testParse (t, "12:34+01:00", 11, 0, 0, 0, 0, 0, 0, hm, 3600, false, utc+hm-z+ud );
testParse (t, "12:34+01", 8, 0, 0, 0, 0, 0, 0, hm, 3600, false, utc+hm-z+ud );
testParse (t, "12+01:00", 8, 0, 0, 0, 0, 0, 0, h, 3600, false, utc+h-z+ud );
testParse (t, "12+01", 5, 0, 0, 0, 0, 0, 0, h, 3600, false, utc+h-z+ud );
testParse (t, "12:34:56", 8, 0, 0, 0, 0, 0, 0, hms, 0, false, local+hms+ld );
testParse (t, "12:34", 5, 0, 0, 0, 0, 0, 0, hm, 0, false, local+hm+ld );
#ifdef AMBIGUOUS
testParse (t, "12", 2, 0, 0, 0, 0, 0, 0, h, 0, false, local+h+ld );
#endif
// time
// input i Year Mo Wk WD Jul Da Secs TZ UTC time_t
testParse (t, "123456Z", 7, 0, 0, 0, 0, 0, 0, hms, 0, true, utc+hms+ud );
testParse (t, "1234Z", 5, 0, 0, 0, 0, 0, 0, hm, 0, true, utc+hm+ud );
testParse (t, "123456+0100", 11, 0, 0, 0, 0, 0, 0, hms, 3600, false, utc+hms-z+ud );
testParse (t, "123456+01", 9, 0, 0, 0, 0, 0, 0, hms, 3600, false, utc+hms-z+ud );
testParse (t, "1234+0100", 9, 0, 0, 0, 0, 0, 0, hm, 3600, false, utc+hm-z+ud );
testParse (t, "1234+01", 7, 0, 0, 0, 0, 0, 0, hm, 3600, false, utc+hm-z+ud );
testParse (t, "12+0100", 7, 0, 0, 0, 0, 0, 0, h, 3600, false, utc+h-z+ud );
#ifdef AMBIGUOUS
testParse (t, "123456", 6, 0, 0, 0, 0, 0, 0, hms, 0, false, local+hms+ld );
#endif
// datetime-ext
// input i Year Mo Wk WD Jul Da Secs TZ UTC time_t
testParse (t, "2013-12-06", 10, 2013, 12, 0, 0, 0, 6, 0, 0, false, local6 );
testParse (t, "2013-340", 8, 2013, 0, 0, 0, 340, 0, 0, 0, false, local6 );
testParse (t, "2013-W49-5", 10, 2013, 0, 49, 5, 0, 0, 0, 0, false, local6 );
testParse (t, "2013-W49", 8, 2013, 0, 49, 0, 0, 0, 0, 0, false, local1 );
testParse (t, "2013-12-06T12:34:56", 19, 2013, 12, 0, 0, 0, 6, hms, 0, false, local6+hms);
testParse (t, "2013-12-06T12:34", 16, 2013, 12, 0, 0, 0, 6, hm, 0, false, local6+hm );
testParse (t, "2013-340T12:34:56", 17, 2013, 0, 0, 0, 340, 0, hms, 0, false, local6+hms);
testParse (t, "2013-340T12:34", 14, 2013, 0, 0, 0, 340, 0, hm, 0, false, local6+hm );
testParse (t, "2013-W49-5T12:34:56", 19, 2013, 0, 49, 5, 0, 0, hms, 0, false, local6+hms);
testParse (t, "2013-W49-5T12:34", 16, 2013, 0, 49, 5, 0, 0, hm, 0, false, local6+hm );
testParse (t, "2013-W49T12:34:56", 17, 2013, 0, 49, 0, 0, 0, hms, 0, false, local1+hms);
testParse (t, "2013-W49T12:34", 14, 2013, 0, 49, 0, 0, 0, hm, 0, false, local1+hm );
testParse (t, "2013-12-06T12:34:56Z", 20, 2013, 12, 0, 0, 0, 6, hms, 0, true, utc6+hms );
testParse (t, "2013-12-06T12:34Z", 17, 2013, 12, 0, 0, 0, 6, hm, 0, true, utc6+hm );
testParse (t, "2013-340T12:34:56Z", 18, 2013, 0, 0, 0, 340, 0, hms, 0, true, utc6+hms );
testParse (t, "2013-340T12:34Z", 15, 2013, 0, 0, 0, 340, 0, hm, 0, true, utc6+hm );
testParse (t, "2013-W49-5T12:34:56Z", 20, 2013, 0, 49, 5, 0, 0, hms, 0, true, utc6+hms );
testParse (t, "2013-W49-5T12:34Z", 17, 2013, 0, 49, 5, 0, 0, hm, 0, true, utc6+hm );
testParse (t, "2013-W49T12:34:56Z", 18, 2013, 0, 49, 0, 0, 0, hms, 0, true, utc1+hms );
testParse (t, "2013-W49T12:34Z", 15, 2013, 0, 49, 0, 0, 0, hm, 0, true, utc1+hm );
testParse (t, "2013-12-06T12:34:56+01:00", 25, 2013, 12, 0, 0, 0, 6, hms, 3600, false, utc6+hms-z);
testParse (t, "2013-12-06T12:34:56+01", 22, 2013, 12, 0, 0, 0, 6, hms, 3600, false, utc6+hms-z);
testParse (t, "2013-12-06T12:34:56-01:00", 25, 2013, 12, 0, 0, 0, 6, hms, -3600, false, utc6+hms+z);
testParse (t, "2013-12-06T12:34:56-01", 22, 2013, 12, 0, 0, 0, 6, hms, -3600, false, utc6+hms+z);
testParse (t, "2013-12-06T12:34+01:00", 22, 2013, 12, 0, 0, 0, 6, hm, 3600, false, utc6+hm-z );
testParse (t, "2013-12-06T12:34+01", 19, 2013, 12, 0, 0, 0, 6, hm, 3600, false, utc6+hm-z );
testParse (t, "2013-12-06T12:34-01:00", 22, 2013, 12, 0, 0, 0, 6, hm, -3600, false, utc6+hm+z );
testParse (t, "2013-12-06T12:34-01", 19, 2013, 12, 0, 0, 0, 6, hm, -3600, false, utc6+hm+z );
testParse (t, "2013-340T12:34:56+01:00", 23, 2013, 0, 0, 0, 340, 0, hms, 3600, false, utc6+hms-z);
testParse (t, "2013-340T12:34:56+01", 20, 2013, 0, 0, 0, 340, 0, hms, 3600, false, utc6+hms-z);
testParse (t, "2013-340T12:34:56-01:00", 23, 2013, 0, 0, 0, 340, 0, hms, -3600, false, utc6+hms+z);
testParse (t, "2013-340T12:34:56-01", 20, 2013, 0, 0, 0, 340, 0, hms, -3600, false, utc6+hms+z);
testParse (t, "2013-340T12:34+01:00", 20, 2013, 0, 0, 0, 340, 0, hm, 3600, false, utc6+hm-z );
testParse (t, "2013-340T12:34+01", 17, 2013, 0, 0, 0, 340, 0, hm, 3600, false, utc6+hm-z );
testParse (t, "2013-340T12:34-01:00", 20, 2013, 0, 0, 0, 340, 0, hm, -3600, false, utc6+hm+z );
testParse (t, "2013-340T12:34-01", 17, 2013, 0, 0, 0, 340, 0, hm, -3600, false, utc6+hm+z );
testParse (t, "2013-W49-5T12:34:56+01:00", 25, 2013, 0, 49, 5, 0, 0, hms, 3600, false, utc6+hms-z);
testParse (t, "2013-W49-5T12:34:56+01", 22, 2013, 0, 49, 5, 0, 0, hms, 3600, false, utc6+hms-z);
testParse (t, "2013-W49-5T12:34:56-01:00", 25, 2013, 0, 49, 5, 0, 0, hms, -3600, false, utc6+hms+z);
testParse (t, "2013-W49-5T12:34:56-01", 22, 2013, 0, 49, 5, 0, 0, hms, -3600, false, utc6+hms+z);
testParse (t, "2013-W49-5T12:34+01:00", 22, 2013, 0, 49, 5, 0, 0, hm, 3600, false, utc6+hm-z );
testParse (t, "2013-W49-5T12:34+01", 19, 2013, 0, 49, 5, 0, 0, hm, 3600, false, utc6+hm-z );
testParse (t, "2013-W49-5T12:34-01:00", 22, 2013, 0, 49, 5, 0, 0, hm, -3600, false, utc6+hm+z );
testParse (t, "2013-W49-5T12:34-01", 19, 2013, 0, 49, 5, 0, 0, hm, -3600, false, utc6+hm+z );
testParse (t, "2013-W49T12:34:56+01:00", 23, 2013, 0, 49, 0, 0, 0, hms, 3600, false, utc1+hms-z);
testParse (t, "2013-W49T12:34:56+01", 20, 2013, 0, 49, 0, 0, 0, hms, 3600, false, utc1+hms-z);
testParse (t, "2013-W49T12:34:56-01:00", 23, 2013, 0, 49, 0, 0, 0, hms, -3600, false, utc1+hms+z);
testParse (t, "2013-W49T12:34:56-01", 20, 2013, 0, 49, 0, 0, 0, hms, -3600, false, utc1+hms+z);
testParse (t, "2013-W49T12:34+01:00", 20, 2013, 0, 49, 0, 0, 0, hm, 3600, false, utc1+hm-z );
testParse (t, "2013-W49T12:34+01", 17, 2013, 0, 49, 0, 0, 0, hm, 3600, false, utc1+hm-z );
testParse (t, "2013-W49T12:34-01:00", 20, 2013, 0, 49, 0, 0, 0, hm, -3600, false, utc1+hm+z );
testParse (t, "2013-W49T12:34-01", 17, 2013, 0, 49, 0, 0, 0, hm, -3600, false, utc1+hm+z );
// datetime
#ifdef AMBIGUOUS
testParse (t, "20131206", 8, 2013, 12, 0, 0, 0, 6, 0, 0, false, local6 );
#endif
testParse (t, "2013W495", 8, 2013, 0, 49, 5, 0, 0, 0, 0, false, local6 );
testParse (t, "2013W49", 7, 2013, 0, 49, 0, 0, 0, 0, 0, false, local1 );
#ifdef AMBIGUOUS
testParse (t, "2013340", 7, 2013, 0, 0, 0, 340, 0, 0, 0, false, local6 );
#endif
testParse (t, "2013-12", 7, 2013, 12, 0, 0, 0, 0, 0, 0, false, local1 );
testParse (t, "20131206T123456", 15, 2013, 12, 0, 0, 0, 6, hms, 0, false, local6+hms);
testParse (t, "20131206T12", 11, 2013, 12, 0, 0, 0, 6, h, 0, false, local6+h );
testParse (t, "2013W495T123456", 15, 2013, 0, 49, 5, 0, 0, hms, 0, false, local6+hms);
testParse (t, "2013W495T12", 11, 2013, 0, 49, 5, 0, 0, h, 0, false, local6+h );
testParse (t, "2013W49T123456", 14, 2013, 0, 49, 0, 0, 0, hms, 0, false, local1+hms);
testParse (t, "2013W49T12", 10, 2013, 0, 49, 0, 0, 0, h, 0, false, local1+h );
testParse (t, "2013340T123456", 14, 2013, 0, 0, 0, 340, 0, hms, 0, false, local6+hms);
testParse (t, "2013340T12", 10, 2013, 0, 0, 0, 340, 0, h, 0, false, local6+h );
testParse (t, "2013-12T1234", 12, 2013, 12, 0, 0, 0, 0, hm, 0, false, local1+hm );
testParse (t, "2013-12T12", 10, 2013, 12, 0, 0, 0, 0, h, 0, false, local1+h );
testParse (t, "20131206T123456Z", 16, 2013, 12, 0, 0, 0, 6, hms, 0, true, utc6+hms );
testParse (t, "20131206T12Z", 12, 2013, 12, 0, 0, 0, 6, h, 0, true, utc6+h );
testParse (t, "2013W495T123456Z", 16, 2013, 0, 49, 5, 0, 0, hms, 0, true, utc6+hms );
testParse (t, "2013W495T12Z", 12, 2013, 0, 49, 5, 0, 0, h, 0, true, utc6+h );
testParse (t, "2013W49T123456Z", 15, 2013, 0, 49, 0, 0, 0, hms, 0, true, utc1+hms );
testParse (t, "2013W49T12Z", 11, 2013, 0, 49, 0, 0, 0, h, 0, true, utc1+h );
testParse (t, "2013340T123456Z", 15, 2013, 0, 0, 0, 340, 0, hms, 0, true, utc6+hms );
testParse (t, "2013340T12Z", 11, 2013, 0, 0, 0, 340, 0, h, 0, true, utc6+h );
testParse (t, "2013-12T123456Z", 15, 2013, 12, 0, 0, 0, 0, hms, 0, true, utc1+hms );
testParse (t, "2013-12T12Z", 11, 2013, 12, 0, 0, 0, 0, h, 0, true, utc1+h );
testParse (t, "20131206T123456+0100", 20, 2013, 12, 0, 0, 0, 6, hms, 3600, false, utc6+hms-z);
testParse (t, "20131206T123456+01", 18, 2013, 12, 0, 0, 0, 6, hms, 3600, false, utc6+hms-z);
testParse (t, "20131206T123456-0100", 20, 2013, 12, 0, 0, 0, 6, hms, -3600, false, utc6+hms+z);
testParse (t, "20131206T123456-01", 18, 2013, 12, 0, 0, 0, 6, hms, -3600, false, utc6+hms+z);
testParse (t, "20131206T12+0100", 16, 2013, 12, 0, 0, 0, 6, h, 3600, false, utc6+h-z );
testParse (t, "20131206T12+01", 14, 2013, 12, 0, 0, 0, 6, h, 3600, false, utc6+h-z );
testParse (t, "20131206T12-0100", 16, 2013, 12, 0, 0, 0, 6, h, -3600, false, utc6+h+z );
testParse (t, "20131206T12-01", 14, 2013, 12, 0, 0, 0, 6, h, -3600, false, utc6+h+z );
testParse (t, "2013W495T123456+0100", 20, 2013, 0, 49, 5, 0, 0, hms, 3600, false, utc6+hms-z);
testParse (t, "2013W495T123456+01", 18, 2013, 0, 49, 5, 0, 0, hms, 3600, false, utc6+hms-z);
testParse (t, "2013W495T123456-0100", 20, 2013, 0, 49, 5, 0, 0, hms, -3600, false, utc6+hms+z);
testParse (t, "2013W495T123456-01", 18, 2013, 0, 49, 5, 0, 0, hms, -3600, false, utc6+hms+z);
testParse (t, "2013W495T12+0100", 16, 2013, 0, 49, 5, 0, 0, h, 3600, false, utc6+h-z );
testParse (t, "2013W495T12+01", 14, 2013, 0, 49, 5, 0, 0, h, 3600, false, utc6+h-z );
testParse (t, "2013W495T12-0100", 16, 2013, 0, 49, 5, 0, 0, h, -3600, false, utc6+h+z );
testParse (t, "2013W495T12-01", 14, 2013, 0, 49, 5, 0, 0, h, -3600, false, utc6+h+z );
testParse (t, "2013W49T123456+0100", 19, 2013, 0, 49, 0, 0, 0, hms, 3600, false, utc1+hms-z);
testParse (t, "2013W49T123456+01", 17, 2013, 0, 49, 0, 0, 0, hms, 3600, false, utc1+hms-z);
testParse (t, "2013W49T123456-0100", 19, 2013, 0, 49, 0, 0, 0, hms, -3600, false, utc1+hms+z);
testParse (t, "2013W49T123456-01", 17, 2013, 0, 49, 0, 0, 0, hms, -3600, false, utc1+hms+z);
testParse (t, "2013W49T12+0100", 15, 2013, 0, 49, 0, 0, 0, h, 3600, false, utc1+h-z );
testParse (t, "2013W49T12+01", 13, 2013, 0, 49, 0, 0, 0, h, 3600, false, utc1+h-z );
testParse (t, "2013W49T12-0100", 15, 2013, 0, 49, 0, 0, 0, h, -3600, false, utc1+h+z );
testParse (t, "2013W49T12-01", 13, 2013, 0, 49, 0, 0, 0, h, -3600, false, utc1+h+z );
testParse (t, "2013340T123456+0100", 19, 2013, 0, 0, 0, 340, 0, hms, 3600, false, utc6+hms-z);
testParse (t, "2013340T123456+01", 17, 2013, 0, 0, 0, 340, 0, hms, 3600, false, utc6+hms-z);
testParse (t, "2013340T123456-0100", 19, 2013, 0, 0, 0, 340, 0, hms, -3600, false, utc6+hms+z);
testParse (t, "2013340T123456-01", 17, 2013, 0, 0, 0, 340, 0, hms, -3600, false, utc6+hms+z);
testParse (t, "2013340T12+0100", 15, 2013, 0, 0, 0, 340, 0, h, 3600, false, utc6+h-z );
testParse (t, "2013340T12+01", 13, 2013, 0, 0, 0, 340, 0, h, 3600, false, utc6+h-z );
testParse (t, "2013340T12-0100", 15, 2013, 0, 0, 0, 340, 0, h, -3600, false, utc6+h+z );
testParse (t, "2013340T12-01", 13, 2013, 0, 0, 0, 340, 0, h, -3600, false, utc6+h+z );
testParse (t, "2013-12T123456+0100", 19, 2013, 12, 0, 0, 0, 0, hms, 3600, false, utc1+hms-z);
testParse (t, "2013-12T123456+01", 17, 2013, 12, 0, 0, 0, 0, hms, 3600, false, utc1+hms-z);
testParse (t, "2013-12T123456-0100", 19, 2013, 12, 0, 0, 0, 0, hms, -3600, false, utc1+hms+z);
testParse (t, "2013-12T123456-01", 17, 2013, 12, 0, 0, 0, 0, hms, -3600, false, utc1+hms+z);
testParse (t, "2013-12T12+0100", 15, 2013, 12, 0, 0, 0, 0, h, 3600, false, utc1+h-z );
testParse (t, "2013-12T12+01", 13, 2013, 12, 0, 0, 0, 0, h, 3600, false, utc1+h-z );
testParse (t, "2013-12T12-0100", 15, 2013, 12, 0, 0, 0, 0, h, -3600, false, utc1+h+z );
testParse (t, "2013-12T12-01", 13, 2013, 12, 0, 0, 0, 0, h, -3600, false, utc1+h+z );
// TODO Test validation of individual values.
return 0;
}
////////////////////////////////////////////////////////////////////////////////

122
test/iso8601p.t.cpp Normal file
View file

@ -0,0 +1,122 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2013 - 2014, Göteborg Bit Factory.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////
#include <cmake.h>
#include <iostream>
#include <time.h>
#include <test.h>
#include <ISO8601.h>
#include <Context.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
void testParse (
UnitTest& t,
const std::string& input,
int in_start,
int in_year,
int in_month,
int in_day,
int in_hours,
int in_minutes,
int in_seconds,
time_t in_value)
{
std::string label = std::string ("parse (\"") + input + "\") --> ";
ISO8601p iso;
std::string::size_type start = 0;
t.ok (iso.parse (input, start), label + "true");
t.is ((int) start, in_start, label + "[]");
t.is (iso._year, in_year, label + "_year");
t.is (iso._month, in_month, label + "_month");
t.is (iso._day, in_day, label + "_day");
t.is (iso._hours, in_hours, label + "_hours");
t.is (iso._minutes, in_minutes, label + "_minutes");
t.is (iso._seconds, in_seconds, label + "_seconds");
t.is ((size_t) iso._value, (size_t) in_value, label + "_value");
}
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
UnitTest t (183);
ISO8601p iso;
std::string::size_type start = 0;
t.notok (iso.parse ("foo", start), "foo --> false");
t.is ((int)start, 0, "foo[0]");
t.notok (iso.parse ("P", start), "P --> false");
t.is ((int)start, 0, "P[0]");
t.notok (iso.parse ("PT", start), "PT --> false");
t.is ((int)start, 0, "PT[0]");
t.notok (iso.parse ("P1", start), "P1 --> false");
t.is ((int)start, 0, "P1[0]");
t.notok (iso.parse ("P1T", start), "P1T --> false");
t.is ((int)start, 0, "P1T[0]");
t.notok (iso.parse ("PT1", start), "PT1 --> false");
t.is ((int)start, 0, "PT1[0]");
int year = 365 * 86400;
int month = 30 * 86400;
int day = 86400;
int h = 3600;
int m = 60;
// Designated.
// input i Year Mo Da Ho Mi Se time_t
testParse (t, "P1Y", 3, 1, 0, 0, 0, 0, 0, year);
testParse (t, "P1M", 3, 0, 1, 0, 0, 0, 0, month);
testParse (t, "P1D", 3, 0, 0, 1, 0, 0, 0, day);
testParse (t, "P1Y1M", 5, 1, 1, 0, 0, 0, 0, year + month);
testParse (t, "P1Y1D", 5, 1, 0, 1, 0, 0, 0, year + day);
testParse (t, "P1M1D", 5, 0, 1, 1, 0, 0, 0, month + day);
testParse (t, "P1Y1M1D", 7, 1, 1, 1, 0, 0, 0, year + month + day);
testParse (t, "PT1H", 4, 0, 0, 0, 1, 0, 0, h);
testParse (t, "PT1M", 4, 0, 0, 0, 0, 1, 0, m);
testParse (t, "PT1S", 4, 0, 0, 0, 0, 0, 1, 1);
testParse (t, "PT1H1M", 6, 0, 0, 0, 1, 1, 0, h + m);
testParse (t, "PT1H1S", 6, 0, 0, 0, 1, 0, 1, h + 1);
testParse (t, "PT1M1S", 6, 0, 0, 0, 0, 1, 1, m + 1);
testParse (t, "PT1H1M1S", 8, 0, 0, 0, 1, 1, 1, h + m + 1);
testParse (t, "P1Y1M1DT1H1M1S", 14, 1, 1, 1, 1, 1, 1, year + month + day + h + m + 1);
testParse (t, "PT24H", 5, 0, 0, 0, 24, 0, 0, day);
testParse (t, "PT40000000S", 11, 0, 0, 0, 0, 0, 40000000, 40000000);
testParse (t, "PT3600S", 7, 0, 0, 0, 0, 0, 3600, h);
testParse (t, "PT60M", 5, 0, 0, 0, 0, 60, 0, h);
return 0;
}
////////////////////////////////////////////////////////////////////////////////