Duration: Obsolete, removed

This commit is contained in:
Paul Beckingham
2015-08-12 11:41:15 -04:00
parent 14b36a5dc6
commit 565232eccd
6 changed files with 2 additions and 804 deletions

View File

@@ -12,7 +12,6 @@ set (task_SRCS CLI2.cpp CLI2.h
DOM.cpp DOM.h DOM.cpp DOM.h
Date.cpp Date.h Date.cpp Date.h
Dates.cpp Dates.h Dates.cpp Dates.h
Duration.cpp Duration.h
Eval.cpp Eval.h Eval.cpp Eval.h
Filter.cpp Filter.h Filter.cpp Filter.h
FS.cpp FS.h FS.cpp FS.h

View File

@@ -1,388 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, 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 <sstream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Nibbler.h>
#include <Lexer.h>
#include <Duration.h>
#include <text.h>
#define DAY 86400
#define HOUR 3600
#define MINUTE 60
#define SECOND 1
static struct
{
std::string unit;
int seconds;
bool standalone;
} durations[] =
{
// These are sorted by first character, then length, so that Nibbler::getOneOf
// returns a maximal match.
{"annual", 365 * DAY, true},
{"biannual", 730 * DAY, true},
{"bimonthly", 61 * DAY, true},
{"biweekly", 14 * DAY, true},
{"biyearly", 730 * DAY, true},
{"daily", 1 * DAY, true},
{"days", 1 * DAY, false},
{"day", 1 * DAY, true},
{"d", 1 * DAY, false},
{"fortnight", 14 * DAY, true},
{"hours", 1 * HOUR, false},
{"hour", 1 * HOUR, true},
{"hrs", 1 * HOUR, false},
{"hr", 1 * HOUR, true},
{"h", 1 * HOUR, false},
{"minutes", 1 * MINUTE, false},
{"minute", 1 * MINUTE, true},
{"mins", 1 * MINUTE, false},
{"min", 1 * MINUTE, true},
{"monthly", 30 * DAY, true},
{"months", 30 * DAY, false},
{"month", 30 * DAY, true},
{"mnths", 30 * DAY, false},
{"mths", 30 * DAY, false},
{"mth", 30 * DAY, true},
{"mos", 30 * DAY, false},
{"mo", 30 * DAY, true},
{"m", 30 * DAY, false},
{"quarterly", 91 * DAY, true},
{"quarters", 91 * DAY, false},
{"quarter", 91 * DAY, true},
{"qrtrs", 91 * DAY, false},
{"qrtr", 91 * DAY, true},
{"qtrs", 91 * DAY, false},
{"qtr", 91 * DAY, true},
{"q", 91 * DAY, false},
{"semiannual", 183 * DAY, true},
{"sennight", 14 * DAY, false},
{"seconds", 1 * SECOND, false},
{"second", 1 * SECOND, true},
{"secs", 1 * SECOND, false},
{"sec", 1 * SECOND, true},
{"s", 1 * SECOND, false},
{"weekdays", 1 * DAY, true},
{"weekly", 7 * DAY, true},
{"weeks", 7 * DAY, false},
{"week", 7 * DAY, true},
{"wks", 7 * DAY, false},
{"wk", 7 * DAY, true},
{"w", 7 * DAY, false},
{"yearly", 365 * DAY, true},
{"years", 365 * DAY, false},
{"year", 365 * DAY, true},
{"yrs", 365 * DAY, false},
{"yr", 365 * DAY, true},
{"y", 365 * DAY, false},
};
#define NUM_DURATIONS (sizeof (durations) / sizeof (durations[0]))
////////////////////////////////////////////////////////////////////////////////
Duration::Duration ()
: _secs (0)
{
}
////////////////////////////////////////////////////////////////////////////////
Duration::Duration (time_t input)
: _secs (input)
{
}
////////////////////////////////////////////////////////////////////////////////
Duration::Duration (const std::string& input)
: _secs (0)
{
if (Lexer::isAllDigits (input))
{
time_t value = (time_t) strtol (input.c_str (), NULL, 10);
if (value == 0 || value > 60)
{
_secs = value;
return;
}
}
std::string::size_type idx = 0;
parse (input, idx);
}
////////////////////////////////////////////////////////////////////////////////
Duration::~Duration ()
{
}
////////////////////////////////////////////////////////////////////////////////
bool Duration::operator< (const Duration& other)
{
return _secs < other._secs;
}
////////////////////////////////////////////////////////////////////////////////
bool Duration::operator> (const Duration& other)
{
return _secs > other._secs;
}
////////////////////////////////////////////////////////////////////////////////
Duration& Duration::operator= (const Duration& other)
{
if (this != &other)
_secs = other._secs;
return *this;
}
////////////////////////////////////////////////////////////////////////////////
Duration::operator time_t () const
{
return _secs;
}
////////////////////////////////////////////////////////////////////////////////
Duration::operator std::string () const
{
std::stringstream s;
s << _secs;
return s.str ();
}
////////////////////////////////////////////////////////////////////////////////
std::string Duration::format () const
{
char formatted[24];
float days = (float) _secs / 86400.0;
if (_secs >= 86400 * 365)
sprintf (formatted, "%.1f year%s",
(days / 365),
((int) (float) (days / 365) == 1 ? "" : "s"));
else if (_secs > 86400 * 84)
sprintf (formatted, "%1d month%s",
(int) (float) (days / 30),
((int) (float) (days / 30) == 1 ? "" : "s"));
else if (_secs > 86400 * 13)
sprintf (formatted, "%d week%s",
(int) (float) (days / 7.0),
((int) (float) (days / 7.0) == 1 ? "" : "s"));
else if (_secs >= 86400)
sprintf (formatted, "%d day%s",
(int) days,
((int) days == 1 ? "" : "s"));
else if (_secs >= 3600)
sprintf (formatted, "%d hour%s",
(int) (float) (_secs / 3600),
((int) (float) (_secs / 3600) == 1 ? "" : "s"));
else if (_secs >= 60)
sprintf (formatted, "%d minute%s",
(int) (float) (_secs / 60),
((int) (float) (_secs / 60) == 1 ? "" : "s"));
else if (_secs >= 1)
sprintf (formatted, "%d second%s",
(int) _secs,
((int) _secs == 1 ? "" : "s"));
else
strcpy (formatted, "-"); // no i18n
return std::string (formatted);
}
////////////////////////////////////////////////////////////////////////////////
std::string Duration::formatCompact () const
{
char formatted[24];
float days = (float) _secs / 86400.0;
if (_secs >= 86400 * 365) sprintf (formatted, "%.1fy", (days / 365.0));
else if (_secs >= 86400 * 84) sprintf (formatted, "%1dmo", (int) (days / 30));
else if (_secs >= 86400 * 13) sprintf (formatted, "%dw", (int) (float) (days / 7.0));
else if (_secs >= 86400) sprintf (formatted, "%dd", (int) days);
else if (_secs >= 3600) sprintf (formatted, "%dh", (int) (_secs / 3600));
else if (_secs >= 60) sprintf (formatted, "%dmin", (int) (_secs / 60));
else if (_secs >= 1) sprintf (formatted, "%ds", (int) _secs);
else formatted[0] = '\0';
return std::string (formatted);
}
////////////////////////////////////////////////////////////////////////////////
std::string Duration::formatPrecise () const
{
char formatted[24];
int days = _secs / 86400;
int hours = (_secs % 86400) / 3600;
int minutes = (_secs % 3600) / 60;
int seconds = _secs % 60;
if (days > 0) sprintf (formatted, "%dd %d:%02d:%02d", days, hours, minutes, seconds);
else sprintf (formatted, "%d:%02d:%02d", hours, minutes, seconds);
return std::string (formatted);
}
////////////////////////////////////////////////////////////////////////////////
std::string Duration::formatSeconds () const
{
char formatted[24];
sprintf (formatted, "%llus", (unsigned long long)_secs);
return std::string (formatted);
}
////////////////////////////////////////////////////////////////////////////////
std::string Duration::formatISO () const
{
if (_secs)
{
time_t t = _secs;
int seconds = t % 60; t /= 60;
int minutes = t % 60; t /= 60;
int hours = t % 24; t /= 24;
int days = t % 30; t /= 30;
int months = t % 12; t /= 12;
int years = t;
std::stringstream s;
s << 'P';
if (years) s << years << 'Y';
if (months) s << months << 'M';
if (days) s << days << 'D';
if (hours || minutes || seconds)
{
s << 'T';
if (hours) s << hours << 'H';
if (minutes) s << minutes << 'M';
if (seconds) s << seconds << 'S';
}
return s.str ();
}
else
{
return "PT0S";
}
}
////////////////////////////////////////////////////////////////////////////////
bool Duration::parse (const std::string& input, std::string::size_type& start)
{
auto original_start = start;
Nibbler n (input.substr (start));
// Static and so preserved between calls.
static std::vector <std::string> units;
if (units.size () == 0)
for (unsigned int i = 0; i < NUM_DURATIONS; i++)
units.push_back (durations[i].unit);
std::string number;
std::string unit;
if (n.getOneOf (units, unit))
{
if (n.depleted () ||
Lexer::isWhitespace (n.next ()) ||
Lexer::isSingleCharOperator (n.next ()))
{
start = original_start + n.cursor ();
// Linear lookup - should be logarithmic.
for (unsigned int i = 0; i < NUM_DURATIONS; i++)
{
if (durations[i].unit == unit &&
durations[i].standalone == true)
{
_secs = static_cast <int> (durations[i].seconds);
return true;
}
}
}
}
else if (n.getNumber (number) &&
number.find ('e') == std::string::npos &&
number.find ('E') == std::string::npos &&
(number.find ('+') == std::string::npos || number.find ('+') == 0) &&
(number.find ('-') == std::string::npos || number.find ('-') == 0))
{
n.skipWS ();
if (n.getOneOf (units, unit))
{
// The "d" unit is a special case, because it is the only one that can
// legitimately occur at the beginning of a UUID, and be followed by an
// operator:
//
// 1111111d-0000-0000-0000-000000000000
//
// Because Lexer::isDuration is higher precedence than Lexer::isUUID,
// the above UUID looks like:
//
// <1111111d> <-> ...
// duration op ...
//
// So as a special case, durations, with units of "d" are rejected if the
// quantity exceeds 10000.
//
if (unit == "d" &&
strtol (number.c_str (), NULL, 10) > 10000)
return false;
if (n.depleted () ||
Lexer::isWhitespace (n.next ()) ||
Lexer::isSingleCharOperator (n.next ()))
{
start = original_start + n.cursor ();
double quantity = strtod (number.c_str (), NULL);
// Linear lookup - should be logarithmic.
double seconds = 1;
for (unsigned int i = 0; i < NUM_DURATIONS; i++)
{
if (durations[i].unit == unit)
{
seconds = durations[i].seconds;
_secs = static_cast <int> (quantity * static_cast <double> (seconds));
return true;
}
}
}
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,59 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2015, 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_DURATION
#define INCLUDED_DURATION
#include <string>
#include <time.h>
class Duration
{
public:
Duration (); // Default constructor
Duration (time_t); // Constructor
Duration (const std::string&); // Parse
~Duration (); // Destructor
Duration (const Duration&); // Unimplemented
bool operator< (const Duration&);
bool operator> (const Duration&);
Duration& operator= (const Duration&);
operator time_t () const;
operator std::string () const;
std::string format () const;
std::string formatCompact () const;
std::string formatPrecise () const;
std::string formatSeconds () const;
std::string formatISO () const;
bool parse (const std::string&, std::string::size_type&);
protected:
time_t _secs;
};
#endif
////////////////////////////////////////////////////////////////////////////////

1
test/.gitignore vendored
View File

@@ -9,7 +9,6 @@ color.t
config.t config.t
date.t date.t
dates.t dates.t
duration.t
eval.t eval.t
fs.t fs.t
i18n.t i18n.t

View File

@@ -11,13 +11,13 @@ include_directories (${CMAKE_SOURCE_DIR}
set (test_SRCS autocomplete.t col.t color.t config.t date.t fs.t i18n.t json.t set (test_SRCS autocomplete.t col.t color.t config.t date.t fs.t i18n.t json.t
list.t msg.t nibbler.t rx.t t.t t2.t t3.t tdb2.t text.t utf8.t list.t msg.t nibbler.t rx.t t.t t2.t t3.t tdb2.t text.t utf8.t
util.t view.t json_test lexer.t iso8601d.t iso8601p.t duration.t util.t view.t json_test lexer.t iso8601d.t iso8601p.t eval.t
variant_add.t variant_and.t variant_cast.t variant_divide.t variant_add.t variant_and.t variant_cast.t variant_divide.t
variant_equal.t variant_exp.t variant_gt.t variant_gte.t variant_equal.t variant_exp.t variant_gt.t variant_gte.t
variant_inequal.t variant_lt.t variant_lte.t variant_match.t variant_inequal.t variant_lt.t variant_lte.t variant_match.t
variant_math.t variant_modulo.t variant_multiply.t variant_math.t variant_modulo.t variant_multiply.t
variant_nomatch.t variant_not.t variant_or.t variant_partial.t variant_nomatch.t variant_not.t variant_or.t variant_partial.t
variant_subtract.t variant_xor.t eval.t dates.t) variant_subtract.t variant_xor.t dates.t)
add_custom_target (test ./run_all --verbose add_custom_target (test ./run_all --verbose
DEPENDS ${test_SRCS} task_executable DEPENDS ${test_SRCS} task_executable

View File

@@ -1,353 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2013 - 2015, 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 <test.h>
#include <Duration.h>
#include <Context.h>
Context context;
////////////////////////////////////////////////////////////////////////////////
void testParse (
UnitTest& t,
const std::string& input,
int in_start,
time_t in_value)
{
std::string label = std::string ("parse (\"") + input + "\") --> ";
Duration dur;
std::string::size_type start = 0;
t.ok (dur.parse (input, start), label + "true");
t.is ((int) start, in_start, label + "[]");
t.is ((size_t) (time_t) dur, (size_t) in_value, label + "_secs");
}
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
UnitTest t (451);
Duration dur;
std::string::size_type start = 0;
t.notok (dur.parse ("foo", start), "foo --> false");
t.is ((int)start, 0, "foo[0]");
const int day = 86400;
const int hour = 3600;
const int minute = 60;
const int second = 1;
// Parsing.
testParse (t, "0seconds", 8, 0 * second);
testParse (t, "2 seconds", 9, 2 * second);
testParse (t, "10seconds", 9, 10 * second);
testParse (t, "1.5seconds", 10, 1 * second);
testParse (t, "0second", 7, 0 * second);
testParse (t, "2 second", 8, 2 * second);
testParse (t, "10second", 8, 10 * second);
testParse (t, "1.5second", 9, 1 * second);
testParse (t, "0s", 2, 0 * second);
testParse (t, "2 s", 3, 2 * second);
testParse (t, "10s", 3, 10 * second);
testParse (t, "1.5s", 4, 1 * second);
testParse (t, "0minutes", 8, 0 * minute);
testParse (t, "2 minutes", 9, 2 * minute);
testParse (t, "10minutes", 9, 10 * minute);
testParse (t, "1.5minutes", 10, 90 * second);
testParse (t, "0minute", 7, 0 * minute);
testParse (t, "2 minute", 8, 2 * minute);
testParse (t, "10minute", 8, 10 * minute);
testParse (t, "1.5minute", 9, 90 * second);
testParse (t, "0min", 4, 0 * minute);
testParse (t, "2 min", 5, 2 * minute);
testParse (t, "10min", 5, 10 * minute);
testParse (t, "1.5min", 6, 90 * second);
testParse (t, "0hours", 6, 0 * hour);
testParse (t, "2 hours", 7, 2 * hour);
testParse (t, "10hours", 7, 10 * hour);
testParse (t, "1.5hours", 8, 90 * minute);
testParse (t, "0hour", 5, 0 * hour);
testParse (t, "2 hour", 6, 2 * hour);
testParse (t, "10hour", 6, 10 * hour);
testParse (t, "1.5hour", 7, 90 * minute);
testParse (t, "0h", 2, 0 * hour);
testParse (t, "2 h", 3, 2 * hour);
testParse (t, "10h", 3, 10 * hour);
testParse (t, "1.5h", 4, 90 * minute);
testParse (t, "weekdays", 8, 1 * day);
testParse (t, "daily", 5, 1 * day);
testParse (t, "0days", 5, 0 * day);
testParse (t, "2 days", 6, 2 * day);
testParse (t, "10days", 6, 10 * day);
testParse (t, "1.5days", 7, 36 * hour);
testParse (t, "0day", 4, 0 * day);
testParse (t, "2 day", 5, 2 * day);
testParse (t, "10day", 5, 10 * day);
testParse (t, "1.5day", 6, 36 * hour);
testParse (t, "0d", 2, 0 * day);
testParse (t, "2 d", 3, 2 * day);
testParse (t, "10d", 3, 10 * day);
testParse (t, "1.5d", 4, 36 * hour);
testParse (t, "weekly", 6, 7 * day);
testParse (t, "0weeks", 6, 0 * day);
testParse (t, "2 weeks", 7, 14 * day);
testParse (t, "10weeks", 7, 70 * day);
testParse (t, "1.5weeks", 8, 252 * hour);
testParse (t, "0week", 5, 0 * day);
testParse (t, "2 week", 6, 14 * day);
testParse (t, "10week", 6, 70 * day);
testParse (t, "1.5week", 7, 252 * hour);
testParse (t, "0w", 2, 0 * day);
testParse (t, "2 w", 3, 14 * day);
testParse (t, "10w", 3, 70 * day);
testParse (t, "1.5w", 4, 252 * hour);
testParse (t, "monthly", 7, 30 * day);
testParse (t, "0months", 7, 0 * day);
testParse (t, "2 months", 8, 60 * day);
testParse (t, "10months", 8, 300 * day);
testParse (t, "1.5months", 9, 45 * day);
testParse (t, "0month", 6, 0 * day);
testParse (t, "2 month", 7, 60 * day);
testParse (t, "10month", 7, 300 * day);
testParse (t, "1.5month", 8, 45 * day);
testParse (t, "0mo", 3, 0 * day);
testParse (t, "2 mo", 4, 60 * day);
testParse (t, "10mo", 4, 300 * day);
testParse (t, "1.5mo", 5, 45 * day);
testParse (t, "quarterly", 9, 91 * day);
testParse (t, "0quarters", 9, 0 * day);
testParse (t, "2 quarters", 10, 182 * day);
testParse (t, "10quarters", 10, 910 * day);
testParse (t, "1.5quarters", 11, 3276 * hour);
testParse (t, "0quarter", 8, 0 * day);
testParse (t, "2 quarter", 9, 182 * day);
testParse (t, "10quarter", 9, 910 * day);
testParse (t, "1.5quarter", 10, 3276 * hour);
testParse (t, "0q", 2, 0 * day);
testParse (t, "2 q", 3, 182 * day);
testParse (t, "10q", 3, 910 * day);
testParse (t, "1.5q", 4, 3276 * hour);
testParse (t, "yearly", 6, 365 * day);
testParse (t, "0years", 6, 0 * day);
testParse (t, "2 years", 7, 730 * day);
testParse (t, "10years", 7, 3650 * day);
testParse (t, "1.5years", 8, 13140 * hour);
testParse (t, "0year", 5, 0 * day);
testParse (t, "2 year", 6, 730 * day);
testParse (t, "10year", 6, 3650 * day);
testParse (t, "1.5year", 7, 13140 * hour);
testParse (t, "0y", 2, 0 * day);
testParse (t, "2 y", 3, 730 * day);
testParse (t, "10y", 3, 3650 * day);
testParse (t, "1.5y", 4, 13140 * hour);
testParse (t, "annual", 6, 365 * day);
testParse (t, "biannual", 8, 730 * day);
testParse (t, "bimonthly", 9, 61 * day);
testParse (t, "biweekly", 8, 14 * day);
testParse (t, "biyearly", 8, 730 * day);
testParse (t, "fortnight", 9, 14 * day);
testParse (t, "semiannual", 10, 183 * day);
testParse (t, "0sennight", 9, 0 * day);
testParse (t, "2 sennight", 10, 28 * day);
testParse (t, "10sennight", 10, 140 * day);
testParse (t, "1.5sennight", 11, 21 * day);
Duration d;
// std::string format ();
d = Duration (0); t.is (d.format (), "-", "0 -> -");
d = Duration (1); t.is (d.format (), "1 second", "1 -> 1 second");
d = Duration (2); t.is (d.format (), "2 seconds", "2 -> 2 seconds");
d = Duration (59); t.is (d.format (), "59 seconds", "59 -> 59 seconds");
d = Duration (60); t.is (d.format (), "1 minute", "60 -> 1 minute");
d = Duration (119); t.is (d.format (), "1 minute", "119 -> 1 minute");
d = Duration (120); t.is (d.format (), "2 minutes", "120 -> 2 minutes");
d = Duration (121); t.is (d.format (), "2 minutes", "121 -> 2 minutes");
d = Duration (3599); t.is (d.format (), "59 minutes", "3599 -> 59 minutes");
d = Duration (3600); t.is (d.format (), "1 hour", "3600 -> 1 hour");
d = Duration (3601); t.is (d.format (), "1 hour", "3601 -> 1 hour");
d = Duration (86399); t.is (d.format (), "23 hours", "86399 -> 23 hours");
d = Duration (86400); t.is (d.format (), "1 day", "86400 -> 1 day");
d = Duration (86401); t.is (d.format (), "1 day", "86401 -> 1 day");
d = Duration (14 * 86400 - 1); t.is (d.format (), "1 week", "14 days - 1 s -> 1 week");
d = Duration (14 * 86400); t.is (d.format (), "2 weeks", "14 days -> 2 weeks");
d = Duration (14 * 86400 + 1); t.is (d.format (), "2 weeks", "14 days + 1 s -> 2 weeks");
d = Duration (85 * 86400 - 1); t.is (d.format (), "2 months", "85 days - 1 s -> 2 months");
d = Duration (85 * 86400); t.is (d.format (), "2 months", "85 days -> 2 months");
d = Duration (85 * 86400 + 1); t.is (d.format (), "2 months", "85 days + 1 s -> 2 months");
d = Duration (365 * 86400 - 1); t.is (d.format (), "12 months", "365 days - 1 s -> 12 months");
d = Duration (365 * 86400); t.is (d.format (), "1.0 year", "365 days -> 1.0 year");
d = Duration (365 * 86400 + 1); t.is (d.format (), "1.0 year", "365 days + 1 s -> 1.0 year");
// std::string formatCompact ();
d = Duration (0); t.is (d.formatCompact (), "", "0 ->");
d = Duration (1), t.is (d.formatCompact (), "1s", "1 -> 1s");
d = Duration (2), t.is (d.formatCompact (), "2s", "2 -> 2s");
d = Duration (59), t.is (d.formatCompact (), "59s", "59 -> 59s");
d = Duration (60), t.is (d.formatCompact (), "1min", "60 -> 1min");
d = Duration (119), t.is (d.formatCompact (), "1min", "119 -> 1min");
d = Duration (120), t.is (d.formatCompact (), "2min", "120 -> 2min");
d = Duration (121), t.is (d.formatCompact (), "2min", "121 -> 2min");
d = Duration (3599), t.is (d.formatCompact (), "59min", "3599 -> 59min");
d = Duration (3600), t.is (d.formatCompact (), "1h", "3600 -> 1h");
d = Duration (3601), t.is (d.formatCompact (), "1h", "3601 -> 1h");
d = Duration (86399), t.is (d.formatCompact (), "23h", "86399 -> 23h");
d = Duration (86400), t.is (d.formatCompact (), "1d", "86400 -> 1d");
d = Duration (86401), t.is (d.formatCompact (), "1d", "86401 -> 1d");
d = Duration (14 * 86400 - 1), t.is (d.formatCompact (), "1w", "14 days - 1 s -> 1w");
d = Duration (14 * 86400), t.is (d.formatCompact (), "2w", "14 days -> 2w");
d = Duration (14 * 86400 + 1), t.is (d.formatCompact (), "2w", "14 days + 1 s -> 2w");
d = Duration (85 * 86400 - 1), t.is (d.formatCompact (), "2mo", "85 days - 1 s -> 2mo");
d = Duration (85 * 86400), t.is (d.formatCompact (), "2mo", "85 days -> 2mo");
d = Duration (85 * 86400 + 1), t.is (d.formatCompact (), "2mo", "85 days + 1 s -> 2mo");
d = Duration (365 * 86400 - 1), t.is (d.formatCompact (), "12mo", "365 days - 1 s -> 12mo");
d = Duration (365 * 86400), t.is (d.formatCompact (), "1.0y", "365 days -> 1.0y");
d = Duration (365 * 86400 + 1), t.is (d.formatCompact (), "1.0y", "365 days + 1 s -> 1.0y");
// std::string formatPrecise ();
d = Duration (0); t.is (d.formatPrecise (), "0:00:00", "0 -> 0:00:00");
d = Duration (1); t.is (d.formatPrecise (), "0:00:01", "1 -> 0:00:01");
d = Duration (2); t.is (d.formatPrecise (), "0:00:02", "2 -> 0:00:02");
d = Duration (59); t.is (d.formatPrecise (), "0:00:59", "59 -> 0:00:59");
d = Duration (60); t.is (d.formatPrecise (), "0:01:00", "60 -> 0:01;00");
d = Duration (119); t.is (d.formatPrecise (), "0:01:59", "119 -> 0:01:59");
d = Duration (120); t.is (d.formatPrecise (), "0:02:00", "120 -> 0:02:00");
d = Duration (121); t.is (d.formatPrecise (), "0:02:01", "121 -> 0:02:01");
d = Duration (3599); t.is (d.formatPrecise (), "0:59:59", "3599 -> 0:59:59");
d = Duration (3600); t.is (d.formatPrecise (), "1:00:00", "3600 -> 1:00:00");
d = Duration (3601); t.is (d.formatPrecise (), "1:00:01", "3601 -> 1:00:01");
d = Duration (86399); t.is (d.formatPrecise (), "23:59:59", "86399 -> 23:59:59");
d = Duration (86400); t.is (d.formatPrecise (), "1d 0:00:00", "86400 -> 1d 0:00:00");
d = Duration (86401); t.is (d.formatPrecise (), "1d 0:00:01", "86401 -> 1d 0:00:01");
d = Duration (14 * 86400 - 1); t.is (d.formatPrecise (), "13d 23:59:59", "(14 x 86400) - 1 s -> 13d 23:59:59");
d = Duration (14 * 86400); t.is (d.formatPrecise (), "14d 0:00:00", "(14 x 86400) -> 14d 0:00:00");
d = Duration (14 * 86400 + 1); t.is (d.formatPrecise (), "14d 0:00:01", "(14 x 86400) + 1 -> 14d 0:00:01");
d = Duration (365 * 86400 - 1); t.is (d.formatPrecise (), "364d 23:59:59", "365 days - 1 s -> 364d 23:59:59");
d = Duration (365 * 86400); t.is (d.formatPrecise (), "365d 0:00:00", "365 days -> 365d 0:00:00");
d = Duration (365 * 86400 + 1); t.is (d.formatPrecise (), "365d 0:00:01", "365 days + 1 s -> 365d 0:00:01");
d = Duration (123); t.is (d.formatSeconds (), "123s", "123 -> 123s");
// std::string formatISO ();
d = Duration (0); t.is (d.formatISO (), "PT0S", "0 -> PT0S");
d = Duration (1); t.is (d.formatISO (), "PT1S", "1 -> PT1S");
d = Duration (2); t.is (d.formatISO (), "PT2S", "2 -> PT2S");
d = Duration (59); t.is (d.formatISO (), "PT59S", "59 -> PT59S");
d = Duration (60); t.is (d.formatISO (), "PT1M", "60 -> PT1TM");
d = Duration (119); t.is (d.formatISO (), "PT1M59S", "119 -> PT1M59S");
d = Duration (120); t.is (d.formatISO (), "PT2M", "120 -> PT2M");
d = Duration (121); t.is (d.formatISO (), "PT2M1S", "121 -> PT2M1S");
d = Duration (3599); t.is (d.formatISO (), "PT59M59S", "3599 -> PT59M59S");
d = Duration (3600); t.is (d.formatISO (), "PT1H", "3600 -> PT1H");
d = Duration (3601); t.is (d.formatISO (), "PT1H1S", "3601 -> PT1H1S");
d = Duration (86399); t.is (d.formatISO (), "PT23H59M59S", "86399 -> PT23H59M59S");
d = Duration (86400); t.is (d.formatISO (), "P1D", "86400 -> P1D");
d = Duration (86401); t.is (d.formatISO (), "P1DT1S", "86401 -> P1DT1S");
d = Duration (14 * 86400 - 1); t.is (d.formatISO (), "P13DT23H59M59S", "(14 x 86400) - 1 s -> P13DT23H59M59S");
d = Duration (14 * 86400); t.is (d.formatISO (), "P14D", "(14 x 86400) -> P14D");
d = Duration (14 * 86400 + 1); t.is (d.formatISO (), "P14DT1S", "(14 x 86400) + 1 -> P14DT1S");
d = Duration (365 * 86400 - 1); t.is (d.formatISO (), "P1Y4DT23H59M59S", "365 days - 1 s -> P1Y4DT23H59M59S");
d = Duration (365 * 86400); t.is (d.formatISO (), "P1Y5D", "365 days -> P1Y5D");
d = Duration (365 * 86400 + 1); t.is (d.formatISO (), "P1Y5DT1S", "365 days + 1 s -> P1Y5DT1S");
Duration left, right;
// operator<
left = Duration ("1s"); right = Duration ("2s"); t.ok (left < right, "duration 1s < 2s");
left = Duration ("-2s"); right = Duration ("-1s"); t.ok (left < right, "duration -2s < -1s");
left = Duration ("1s"); right = Duration ("1min"); t.ok (left < right, "duration 1s < 1min");
left = Duration ("1min"); right = Duration ("1h"); t.ok (left < right, "duration 1min < 1h");
left = Duration ("1h"); right = Duration ("1d"); t.ok (left < right, "duration 1h < 1d");
left = Duration ("1d"); right = Duration ("1w"); t.ok (left < right, "duration 1d < 1w");
left = Duration ("1w"); right = Duration ("1mo"); t.ok (left < right, "duration 1w < 1mo");
left = Duration ("1mo"); right = Duration ("1q"); t.ok (left < right, "duration 1mo < 1q");
left = Duration ("1q"); right = Duration ("1y"); t.ok (left < right, "duration 1q < 1y");
left = Duration ("-3s"); right = Duration ("-6s"); t.ok (right < left, "duration -6s < -3s");
// operator>
left = Duration ("2s"); right = Duration ("1s"); t.ok (left > right, "2s > 1s");
left = Duration ("-1s"); right = Duration ("-2s"); t.ok (left > right, "-1s > -2s");
left = Duration ("1min"); right = Duration ("1s"); t.ok (left > right, "1min > 1s");
left = Duration ("1h"); right = Duration ("1min"); t.ok (left > right, "1h > 1min");
left = Duration ("1d"); right = Duration ("1h"); t.ok (left > right, "1d > 1h");
left = Duration ("1w"); right = Duration ("1d"); t.ok (left > right, "1w > 1d");
left = Duration ("1mo"); right = Duration ("1w"); t.ok (left > right, "1mo > 1w");
left = Duration ("1q"); right = Duration ("1mo"); t.ok (left > right, "1q > 1mo");
left = Duration ("1y"); right = Duration ("1q"); t.ok (left > right, "1y > 1q");
left = Duration ("-3s"); right = Duration ("-6s"); t.ok (left > right, "duration -3s > -6s");
// operator<=
left = Duration ("1s"); right = Duration ("2s"); t.ok (left <= right, "duration 1s <= 2s");
left = Duration ("2s"); right = Duration ("2s"); t.ok (left <= right, "duration 1s <= 2s");
left = Duration ("2s"); right = Duration ("1s"); t.notok (left <= right, "duration NOT 1s <= 2s");
// TODO Formatting.
return 0;
}
////////////////////////////////////////////////////////////////////////////////