mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Parsing
- Nibbler learned how to parse formtted dates. Date now uses Nibbler. - Added Nibbler unit tests.
This commit is contained in:
parent
236738c708
commit
a749f83da3
4 changed files with 415 additions and 271 deletions
279
src/Date.cpp
279
src/Date.cpp
|
@ -24,12 +24,14 @@
|
|||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <Nibbler.h>
|
||||
#include <Date.h>
|
||||
#include <text.h>
|
||||
#include <util.h>
|
||||
|
@ -83,13 +85,6 @@ Date::Date (const int m, const int d, const int y,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
Date::Date (const std::string& input, const std::string& format /* = "m/d/Y" */)
|
||||
{
|
||||
int month = 0;
|
||||
int day = 0;
|
||||
int year = -1; // So we can check later.
|
||||
int hour = 0;
|
||||
int minute = 0;
|
||||
int second = 0;
|
||||
|
||||
// Perhaps it is an epoch date, in string form?
|
||||
if (isEpoch (input))
|
||||
return;
|
||||
|
@ -98,268 +93,16 @@ Date::Date (const std::string& input, const std::string& format /* = "m/d/Y" */)
|
|||
if (isRelativeDate (input))
|
||||
return;
|
||||
|
||||
unsigned int i = 0; // Index into input.
|
||||
// Parse an ISO date.
|
||||
Nibbler n (input);
|
||||
if (n.getDateISO (mT) && n.depleted ())
|
||||
return;
|
||||
|
||||
// Format may include: mMdDyYVaAbBhHNSjJ
|
||||
//
|
||||
// Note that the format should never include T or Z, as that interferes with
|
||||
// the potential parsing for ISO dates constructed from the above format.
|
||||
for (unsigned int f = 0; f < format.length (); ++f)
|
||||
{
|
||||
switch (format[f])
|
||||
{
|
||||
// Single or double digit.
|
||||
case 'm':
|
||||
if (i >= input.length () ||
|
||||
! isdigit (input[i]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (m). Expected format '" + format + "'";
|
||||
}
|
||||
// Parse a formatted date.
|
||||
if (n.getDate (format, mT) && n.depleted ())
|
||||
return;
|
||||
|
||||
if (i + 1 < input.length () &&
|
||||
(input[i + 0] == '0' || input[i + 0] == '1') &&
|
||||
isdigit (input[i + 1]))
|
||||
{
|
||||
month = atoi (input.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
month = atoi (input.substr (i, 1).c_str ());
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (i >= input.length () ||
|
||||
! isdigit (input[i]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (d). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
if (i + 1 < input.length () &&
|
||||
(input[i + 0] == '0' || input[i + 0] == '1' || input[i + 0] == '2' || input[i + 0] == '3') &&
|
||||
isdigit (input[i + 1]))
|
||||
{
|
||||
day = atoi (input.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
day = atoi (input.substr (i, 1).c_str ());
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
|
||||
// Double digit.
|
||||
case 'y':
|
||||
if (i + 1 >= input.length () ||
|
||||
! isdigit (input[i + 0]) ||
|
||||
! isdigit (input[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (y). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
year = atoi (input.substr (i, 2).c_str ()) + 2000;
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (i + 1 >= input.length () ||
|
||||
! isdigit (input[i + 0]) ||
|
||||
! isdigit (input[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (M). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
month = atoi (input.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if (i + 1 >= input.length () ||
|
||||
! isdigit (input[i + 0]) ||
|
||||
! isdigit (input[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (D). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
day = atoi (input.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
if (i + 1 >= input.length () ||
|
||||
! isdigit (input[i + 0]) ||
|
||||
! isdigit (input[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (V). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
// Quadruple digit.
|
||||
case 'Y':
|
||||
if (i + 3 >= input.length () ||
|
||||
! isdigit (input[i + 0]) ||
|
||||
! isdigit (input[i + 1]) ||
|
||||
! isdigit (input[i + 2]) ||
|
||||
! isdigit (input[i + 3]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (Y). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
year = atoi (input.substr (i, 4).c_str ());
|
||||
i += 4;
|
||||
break;
|
||||
|
||||
// Short names with 3 characters
|
||||
case 'a':
|
||||
if (i + 2 >= input.length () ||
|
||||
isdigit (input[i + 0]) ||
|
||||
isdigit (input[i + 1]) ||
|
||||
isdigit (input[i + 2]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (a). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
i += 3;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
if (i + 2 >= input.length () ||
|
||||
isdigit (input[i + 0]) ||
|
||||
isdigit (input[i + 1]) ||
|
||||
isdigit (input[i + 2]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (b). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
month = Date::monthOfYear (input.substr (i, 3).c_str());
|
||||
i += 3;
|
||||
break;
|
||||
|
||||
// Long names
|
||||
case 'A':
|
||||
if (i + 2 >= input.length () ||
|
||||
isdigit (input[i + 0]) ||
|
||||
isdigit (input[i + 1]) ||
|
||||
isdigit (input[i + 2]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (A). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
i += Date::dayName( Date::dayOfWeek (input.substr (i, 3).c_str()) ).size();
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
if (i + 2 >= input.length () ||
|
||||
isdigit (input[i + 0]) ||
|
||||
isdigit (input[i + 1]) ||
|
||||
isdigit (input[i + 2]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (B). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
month = Date::monthOfYear (input.substr (i, 3).c_str());
|
||||
i += Date::monthName(month).size();
|
||||
break;
|
||||
|
||||
// Single or double digit.
|
||||
case 'h':
|
||||
if (i >= input.length () ||
|
||||
! isdigit (input[i]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (h). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
if (i + 1 < input.length () &&
|
||||
(input[i + 0] == '0' || input[i + 0] == '1' || input[i + 0] == '2') &&
|
||||
isdigit (input[i + 1]))
|
||||
{
|
||||
hour = atoi (input.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
hour = atoi (input.substr (i, 1).c_str ());
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
if (i + 1 >= input.length () ||
|
||||
! isdigit (input[i + 0]) ||
|
||||
! isdigit (input[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (H). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
hour = atoi (input.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
if (i + 1 >= input.length () ||
|
||||
! isdigit (input[i + 0]) ||
|
||||
! isdigit (input[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (N). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
minute = atoi (input.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
if (i + 1 >= input.length () ||
|
||||
! isdigit (input[i + 0]) ||
|
||||
! isdigit (input[i + 1]))
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date (S). Expected format '" + format + "'";
|
||||
}
|
||||
|
||||
second = atoi (input.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (i >= input.length () ||
|
||||
input[i] != format[f])
|
||||
{
|
||||
throw std::string ("\"") + input + "\" is not a valid date. Expected format '" + format + "'";
|
||||
}
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Default the year to the current year, for formats that lack Y/y.
|
||||
if (year == -1)
|
||||
{
|
||||
time_t now = time (NULL);
|
||||
struct tm* default_year = localtime (&now);
|
||||
year = default_year->tm_year + 1900;
|
||||
}
|
||||
|
||||
if (i < input.length ())
|
||||
throw std::string ("\"") + input + "\" is not a valid date. Expected format '" + format + "'";
|
||||
|
||||
if (!valid (month, day, year))
|
||||
throw std::string ("\"") + input + "\" is not a valid date but is in a valid format.";
|
||||
|
||||
// Convert to epoch.
|
||||
struct tm t = {0};
|
||||
t.tm_isdst = -1; // Requests that mktime determine summer time effect.
|
||||
t.tm_mday = day;
|
||||
t.tm_mon = month - 1;
|
||||
t.tm_year = year - 1900;
|
||||
t.tm_hour = hour;
|
||||
t.tm_min = minute;
|
||||
t.tm_sec = second;
|
||||
|
||||
mT = mktime (&t);
|
||||
throw std::string ("'") + input + "' is not a valid date in the '" + format + "' format.";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -451,6 +194,8 @@ const std::string Date::toString (const std::string& format /*= "m/d/Y" */) cons
|
|||
case 'H': sprintf (buffer, "%02d", this->hour ()); break;
|
||||
case 'N': sprintf (buffer, "%02d", this->minute ()); break;
|
||||
case 'S': sprintf (buffer, "%02d", this->second ()); break;
|
||||
case 'j': sprintf (buffer, "%d", this->dayOfYear ()); break;
|
||||
case 'J': sprintf (buffer, "%03d", this->dayOfYear ()); break;
|
||||
default: sprintf (buffer, "%c", c); break;
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,8 @@ void Expression::expand_sequence ()
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Nibble the whole thing.
|
||||
// Nibble the whole bloody thing. Nuke it from orbit - it's the only way to be
|
||||
// sure.
|
||||
void Expression::expand_tokens ()
|
||||
{
|
||||
Arguments temp;
|
||||
|
@ -194,10 +195,16 @@ void Expression::expand_tokens ()
|
|||
// Get a list of all operators.
|
||||
std::vector <std::string> operators = Arguments::operator_list ();
|
||||
|
||||
// Look at all args.
|
||||
// Date format, for both parsing and rendering.
|
||||
std::string date_format = context.config.get ("dateformat");
|
||||
|
||||
// Fake polymorphism.
|
||||
std::string s;
|
||||
int i;
|
||||
double d;
|
||||
time_t t;
|
||||
|
||||
// Look at all args.
|
||||
std::vector <std::pair <std::string, std::string> >::iterator arg;
|
||||
for (arg = _args.begin (); arg != _args.end (); ++arg)
|
||||
{
|
||||
|
@ -213,6 +220,12 @@ void Expression::expand_tokens ()
|
|||
else if (n.getInt (i))
|
||||
temp.push_back (std::make_pair (format (i), "int"));
|
||||
|
||||
else if (n.getDateISO (t))
|
||||
temp.push_back (std::make_pair (Date (t).toISO (), "date"));
|
||||
|
||||
else if (n.getDate (date_format, t))
|
||||
temp.push_back (std::make_pair (Date (t).toString (date_format), "date"));
|
||||
|
||||
else
|
||||
temp.push_back (*arg);
|
||||
}
|
||||
|
|
303
src/Nibbler.cpp
303
src/Nibbler.cpp
|
@ -25,12 +25,14 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
#include <Nibbler.h>
|
||||
#include <Date.h>
|
||||
#include <rx.h>
|
||||
|
||||
const char* c_digits = "0123456789";
|
||||
|
@ -584,7 +586,308 @@ bool Nibbler::getDateISO (time_t& t)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getDate (const std::string& format, time_t& t)
|
||||
{
|
||||
std::string::size_type i = mCursor;
|
||||
|
||||
int month = 0;
|
||||
int day = 0;
|
||||
int year = -1; // So we can check later.
|
||||
int hour = 0;
|
||||
int minute = 0;
|
||||
int second = 0;
|
||||
|
||||
for (unsigned int f = 0; f < format.length (); ++f)
|
||||
{
|
||||
switch (format[f])
|
||||
{
|
||||
case 'm':
|
||||
if (i + 2 <= mLength &&
|
||||
(mInput[i + 0] == '0' || mInput[i + 0] == '1') &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
month = atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else if (i + 1 <= mLength &&
|
||||
isdigit (mInput[i + 0]))
|
||||
{
|
||||
month = mInput[i] - '0';
|
||||
i += 1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (i + 2 <= mLength &&
|
||||
isdigit (mInput[i + 1]) &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
day = atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else if (i + 1 <= mLength &&
|
||||
isdigit (mInput[i + 0]))
|
||||
{
|
||||
day = mInput[i] - '0';
|
||||
i += 1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
if (i + 2 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
year = 2000 + atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (i + 2 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
month = atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if (i + 2 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
day = atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
// Merely parse, not extract.
|
||||
case 'V':
|
||||
if (i + 2 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
day = atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
if (i + 4 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]) &&
|
||||
isdigit (mInput[i + 2]) &&
|
||||
isdigit (mInput[i + 3]))
|
||||
{
|
||||
year = atoi (mInput.substr (i, 4).c_str ());
|
||||
i += 4;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
// Merely parse, not extract.
|
||||
case 'a':
|
||||
if (i + 3 <= mLength &&
|
||||
! isdigit (mInput[i + 0]) &&
|
||||
! isdigit (mInput[i + 1]) &&
|
||||
! isdigit (mInput[i + 2]))
|
||||
i += 3;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
// Merely parse, not extract.
|
||||
case 'b':
|
||||
if (i + 3 <= mLength &&
|
||||
! isdigit (mInput[i + 0]) &&
|
||||
! isdigit (mInput[i + 1]) &&
|
||||
! isdigit (mInput[i + 2]))
|
||||
{
|
||||
month = Date::monthOfYear (mInput.substr (i, 3).c_str());
|
||||
i += 3;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
// Merely parse, not extract.
|
||||
case 'A':
|
||||
if (i + 3 <= mLength &&
|
||||
! isdigit (mInput[i + 0]) &&
|
||||
! isdigit (mInput[i + 1]) &&
|
||||
! isdigit (mInput[i + 2]))
|
||||
i += Date::dayName (Date::dayOfWeek (mInput.substr (i, 3).c_str ())).size ();
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
if (i + 3 <= mLength &&
|
||||
! isdigit (mInput[i + 0]) &&
|
||||
! isdigit (mInput[i + 1]) &&
|
||||
! isdigit (mInput[i + 2]))
|
||||
{
|
||||
month = Date::monthOfYear (mInput.substr (i, 3).c_str ());
|
||||
i += Date::monthName (month).size ();
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
if (i + 2 <= mLength &&
|
||||
(mInput[i + 0] == '0' || mInput[i + 0] == '1') &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
hour = atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else if (i + 1 <= mLength &&
|
||||
isdigit (mInput[i + 0]))
|
||||
{
|
||||
hour = atoi (mInput.substr (i, 1).c_str ());
|
||||
i += 1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
if (i + 2 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
hour = atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
if (i + 2 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
minute = atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
if (i + 2 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
second = atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
if (i + 3 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]) &&
|
||||
isdigit (mInput[i + 2]))
|
||||
{
|
||||
day = atoi (mInput.substr (i, 3).c_str ());
|
||||
i += 3;
|
||||
}
|
||||
else if (i + 2 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]))
|
||||
{
|
||||
day = atoi (mInput.substr (i, 2).c_str ());
|
||||
i += 2;
|
||||
}
|
||||
else if (i + 1 <= mLength &&
|
||||
isdigit (mInput[i + 0]))
|
||||
{
|
||||
day = atoi (mInput.substr (i, 1).c_str ());
|
||||
i += 1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
if (i + 3 <= mLength &&
|
||||
isdigit (mInput[i + 0]) &&
|
||||
isdigit (mInput[i + 1]) &&
|
||||
isdigit (mInput[i + 2]))
|
||||
{
|
||||
day = atoi (mInput.substr (i, 3).c_str ());
|
||||
i += 3;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (i + 1 <= mLength &&
|
||||
mInput[i] == format[f])
|
||||
++i;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Default the year to the current year, for formats that lack Y/y.
|
||||
if (year == -1)
|
||||
{
|
||||
time_t now = time (NULL);
|
||||
struct tm* default_year = localtime (&now);
|
||||
year = default_year->tm_year + 1900;
|
||||
}
|
||||
|
||||
// Convert to epoch.
|
||||
struct tm tms = {0};
|
||||
tms.tm_isdst = -1; // Requests that mktime determine summer time effect.
|
||||
|
||||
if (month == 0 && day >= 0 && day <= 365)
|
||||
{
|
||||
tms.tm_yday = day;
|
||||
tms.tm_mon = 0;
|
||||
|
||||
if (! Date::valid (day, year))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
tms.tm_mday = day;
|
||||
tms.tm_mon = month > 0 ? month - 1 : 0;
|
||||
|
||||
if (! Date::valid (month, day, year))
|
||||
return false;
|
||||
}
|
||||
|
||||
tms.tm_year = year - 1900;
|
||||
tms.tm_hour = hour;
|
||||
tms.tm_min = minute;
|
||||
tms.tm_sec = second;
|
||||
|
||||
t = mktime (&tms);
|
||||
std::cout << "# " << year << " " << month << " " << day << " " << hour << " " << minute << " " << second << "\n";
|
||||
mCursor = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <Context.h>
|
||||
#include <Date.h>
|
||||
#include <Nibbler.h>
|
||||
#include <test.h>
|
||||
|
||||
|
@ -33,7 +34,7 @@ Context context;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest t (193);
|
||||
UnitTest t (242);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -42,6 +43,7 @@ int main (int argc, char** argv)
|
|||
int i;
|
||||
double d;
|
||||
time_t ti;
|
||||
Date dt;
|
||||
std::vector <std::string> options;
|
||||
|
||||
// Make sure the nibbler behaves itself with trivial input.
|
||||
|
@ -313,6 +315,87 @@ int main (int argc, char** argv)
|
|||
t.is (ti, 1234567890, "'20090213T233130Z': getDateISO () -> 1234567890");
|
||||
t.ok (n.depleted (), "depleted");
|
||||
|
||||
// bool getDate (time_t&, const std::string&);
|
||||
t.diag ("Nibbler::getDate");
|
||||
n = Nibbler ("1/1/2008");
|
||||
t.ok (n.getDate ("m/d/Y", ti), "m/d/Y ok");
|
||||
dt = Date (ti);
|
||||
t.is (dt.month (), 1, "ctor (std::string) -> m");
|
||||
t.is (dt.day (), 1, "ctor (std::string) -> d");
|
||||
t.is (dt.year (), 2008, "ctor (std::string) -> y");
|
||||
|
||||
n = Nibbler ("20080101");
|
||||
t.ok (n.getDate ("YMD", ti), "YMD ok");
|
||||
dt = Date (ti);
|
||||
t.is (dt.month (), 1, "ctor (std::string) -> m");
|
||||
t.is (dt.day (), 1, "ctor (std::string) -> d");
|
||||
t.is (dt.year (), 2008, "ctor (std::string) -> y");
|
||||
|
||||
n = Nibbler ("12/31/2007");
|
||||
t.ok (n.getDate ("m/d/Y", ti), "m/d/Y ok");
|
||||
dt = Date (ti);
|
||||
t.is (dt.month (), 12, "ctor (std::string) -> m");
|
||||
t.is (dt.day (), 31, "ctor (std::string) -> d");
|
||||
t.is (dt.year (), 2007, "ctor (std::string) -> y");
|
||||
|
||||
n = Nibbler ("20071231");
|
||||
t.ok (n.getDate ("YMD", ti), "YMD ok");
|
||||
dt = Date (ti);
|
||||
t.is (dt.month (), 12, "ctor (std::string) -> m");
|
||||
t.is (dt.day (), 31, "ctor (std::string) -> d");
|
||||
t.is (dt.year (), 2007, "ctor (std::string) -> y");
|
||||
|
||||
n = Nibbler ("Tue 01 Jan 2008 (01)");
|
||||
t.ok (n.getDate ("a D b Y (V)", ti), "a D b Y (V)");
|
||||
dt = Date (ti);
|
||||
t.is (dt.month (), 1, "ctor (std::string) -> m");
|
||||
t.is (dt.day (), 1, "ctor (std::string) -> d");
|
||||
t.is (dt.year (), 2008, "ctor (std::string) -> y");
|
||||
|
||||
n = Nibbler ("Tuesday, January 1, 2008");
|
||||
t.ok (n.getDate ("A, B d, Y", ti), "A, B d, Y ok");
|
||||
dt = Date (ti);
|
||||
t.is (dt.month (), 1, "ctor (std::string) -> m");
|
||||
t.is (dt.day (), 1, "ctor (std::string) -> d");
|
||||
t.is (dt.year (), 2008, "ctor (std::string) -> y");
|
||||
|
||||
n = Nibbler ("v01 Tue 2008-01-01");
|
||||
t.ok (n.getDate ("vV a Y-M-D", ti), "vV a Y-M-D ok");
|
||||
dt = Date (ti);
|
||||
t.is (dt.month (), 1, "ctor (std::string) -> m");
|
||||
t.is (dt.day (), 1, "ctor (std::string) -> d");
|
||||
t.is (dt.year (), 2008, "ctor (std::string) -> y");
|
||||
|
||||
n = Nibbler ("6/7/2010 1:23:45");
|
||||
t.ok (n.getDate ("m/d/Y h:N:S", ti), "m/d/Y h:N:S ok");
|
||||
dt = Date (ti);
|
||||
t.is (dt.month (), 6, "ctor (std::string) -> m");
|
||||
t.is (dt.day (), 7, "ctor (std::string) -> d");
|
||||
t.is (dt.year (), 2010, "ctor (std::string) -> Y");
|
||||
t.is (dt.hour (), 1, "ctor (std::string) -> h");
|
||||
t.is (dt.minute (), 23, "ctor (std::string) -> N");
|
||||
t.is (dt.second (), 45, "ctor (std::string) -> S");
|
||||
|
||||
n = Nibbler ("6/7/2010 01:23:45");
|
||||
t.ok (n.getDate ("m/d/Y H:N:S", ti), "m/d/Y H:N:S ok");
|
||||
dt = Date (ti);
|
||||
t.is (dt.month (), 6, "ctor (std::string) -> m");
|
||||
t.is (dt.day (), 7, "ctor (std::string) -> d");
|
||||
t.is (dt.year (), 2010, "ctor (std::string) -> Y");
|
||||
t.is (dt.hour (), 1, "ctor (std::string) -> h");
|
||||
t.is (dt.minute (), 23, "ctor (std::string) -> N");
|
||||
t.is (dt.second (), 45, "ctor (std::string) -> S");
|
||||
|
||||
n = Nibbler ("6/7/2010 12:34:56");
|
||||
t.ok (n.getDate ("m/d/Y H:N:S", ti), "m/d/Y H:N:S ok");
|
||||
dt = Date (ti);
|
||||
t.is (dt.month (), 6, "ctor (std::string) -> m");
|
||||
t.is (dt.day (), 7, "ctor (std::string) -> d");
|
||||
t.is (dt.year (), 2010, "ctor (std::string) -> Y");
|
||||
t.is (dt.hour (), 12, "ctor (std::string) -> h");
|
||||
t.is (dt.minute (), 34, "ctor (std::string) -> N");
|
||||
t.is (dt.second (), 56, "ctor (std::string) -> S");
|
||||
|
||||
// bool getOneOf (const std::vector <std::string>&, std::string&);
|
||||
t.diag ("Nibbler::getOneOf");
|
||||
options.push_back ("one");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue