Skip to content

Commit

Permalink
Expanded DateTime ISO parsing + added Juneteenth holiday
Browse files Browse the repository at this point in the history
  • Loading branch information
hosseinmoein committed Sep 10, 2023
1 parent 0921518 commit f4a37c2
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 33 deletions.
Binary file modified docs/DateTimeDoc.docx
Binary file not shown.
Binary file modified docs/DateTimeDoc.pdf
Binary file not shown.
41 changes: 30 additions & 11 deletions include/DataFrame/Utils/DateTime.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ enum class DT_FORMAT : unsigned short int {
DT_PRECISE = 11, // e.g. 1516179600.874123908 = Epoch.Nanoseconds
ISO_DT_TM = 12, // e.g. 2015-05-05 13:51:04.000234
ISO_DT = 13, // e.g. 2015-05-05
ISO_DT_NANO = 14, // e.g. 2015-05-05 13:51:04.123456789
};

// DO NOT change the values of these enums. They are offsets to an
Expand Down Expand Up @@ -178,21 +179,27 @@ class DateTime {
// (3) MM/DD/YYYY HH
// (4) MM/DD/YYYY HH:MM
// (5) MM/DD/YYYY HH:MM:SS
// (6) MM/DD/YYYY HH:MM:SS.MMM
// (6) MM/DD/YYYY HH:MM:SS.MMM // Milliseconds
// (7) MM/DD/YYYY HH:MM:SS.IIIIII // Microseconds
// (8) MM/DD/YYYY HH:MM:SS.NNNNNNNNN // Nanoseconds
//
// EUR_STYLE:
// (7) YYYY/MM/DD
// (8) YYYY/MM/DD HH
// (9) YYYY/MM/DD HH:MM
// (10) YYYY/MM/DD HH:MM:SS
// (11) YYYY/MM/DD HH:MM:SS.MMM
// (9) YYYY/MM/DD
// (10) YYYY/MM/DD HH
// (11) YYYY/MM/DD HH:MM
// (12) YYYY/MM/DD HH:MM:SS
// (13) YYYY/MM/DD HH:MM:SS.MMM // Milliseconds
// (14) YYYY/MM/DD HH:MM:SS.IIIIII // Microseconds
// (15) YYYY/MM/DD HH:MM:SS.NNNNNNNNN // Nanoseconds
//
// ISO_STYLE:
// (12) YYYY-MM-DD
// (13) YYYY-MM-DD HH
// (14) YYYY-MM-DD HH:MM
// (15) YYYY-MM-DD HH:MM:SS
// (16) YYYY-MM-DD HH:MM:SS.MMM
// (16) YYYY-MM-DD
// (17) YYYY-MM-DD HH
// (18) YYYY-MM-DD HH:MM
// (19) YYYY-MM-DD HH:MM:SS
// (20) YYYY-MM-DD HH:MM:SS.MMM // Milliseconds
// (21) YYYY-MM-DD HH:MM:SS.IIIIII // Microseconds
// (22) YYYY-MM-DD HH:MM:SS.NNNNNNNNN // Nanoseconds
//
HMDF_API explicit DateTime (const char *s,
DT_DATE_STYLE ds = DT_DATE_STYLE::YYYYMMDD,
Expand Down Expand Up @@ -553,6 +560,18 @@ void DateTime::date_to_str (DT_FORMAT format, T &result) const {
static_cast<int>(dmonth()));
} break;

case DT_FORMAT::ISO_DT_NANO:
{
buffer.printf("%d-%002d-%002d %002d:%002d:%002d.%0000000009d",
static_cast<int>(year()),
static_cast<int>(month()),
static_cast<int>(dmonth()),
static_cast<int>(hour()),
static_cast<int>(minute()),
static_cast<int>(sec()),
static_cast<int>(nanosec()));
} break;

case DT_FORMAT::DT_DATETIME:
{
buffer.printf("%d%002d%002d %002d:%002d:%002d.%0003d",
Expand Down
94 changes: 72 additions & 22 deletions src/Utils/DateTime.cc
Original file line number Diff line number Diff line change
Expand Up @@ -115,28 +115,35 @@ DateTime::DateTime (DateType d,

// ----------------------------------------------------------------------------

// I'm adding the following formats:
//
// Supporting the following formats:

// (1) YYYYMMDD
// AME_STYLE:
// (1) MM/DD/YYYY
// (2) MM/DD/YYYY HH
// (3) MM/DD/YYYY HH:MM
// (4) MM/DD/YYYY HH:MM:SS
// (5) MM/DD/YYYY HH:MM:SS.MMM
//
// (2) MM/DD/YYYY
// (3) MM/DD/YYYY HH
// (4) MM/DD/YYYY HH:MM
// (5) MM/DD/YYYY HH:MM:SS
// (6) MM/DD/YYYY HH:MM:SS.MMM // Milliseconds
// (7) MM/DD/YYYY HH:MM:SS.IIIIII // Microseconds
// (8) MM/DD/YYYY HH:MM:SS.NNNNNNNNN // Nanoseconds

// EUR_STYLE:
// (1) YYYY/MM/DD
// (2) YYYY/MM/DD HH
// (3) YYYY/MM/DD HH:MM
// (4) YYYY/MM/DD HH:MM:SS
// (5) YYYY/MM/DD HH:MM:SS.MMM
//
// (9) YYYY/MM/DD
// (10) YYYY/MM/DD HH
// (11) YYYY/MM/DD HH:MM
// (12) YYYY/MM/DD HH:MM:SS
// (13) YYYY/MM/DD HH:MM:SS.MMM // Milliseconds
// (14) YYYY/MM/DD HH:MM:SS.IIIIII // Microseconds
// (15) YYYY/MM/DD HH:MM:SS.NNNNNNNNN // Nanoseconds

// ISO_STYLE:
// (12) YYYY-MM-DD
// (13) YYYY-MM-DD HH
// (14) YYYY-MM-DD HH:MM
// (15) YYYY-MM-DD HH:MM:SS
// (16) YYYY-MM-DD HH:MM:SS.MMM
// (16) YYYY-MM-DD
// (17) YYYY-MM-DD HH
// (18) YYYY-MM-DD HH:MM
// (19) YYYY-MM-DD HH:MM:SS
// (20) YYYY-MM-DD HH:MM:SS.MMM // Milliseconds
// (21) YYYY-MM-DD HH:MM:SS.IIIIII // Microseconds
// (22) YYYY-MM-DD HH:MM:SS.NNNNNNNNN // Nanoseconds
//
DateTime::DateTime (const char *s, DT_DATE_STYLE ds, DT_TIME_ZONE tz)
: time_zone_ (tz) {
Expand All @@ -151,7 +158,7 @@ DateTime::DateTime (const char *s, DT_DATE_STYLE ds, DT_TIME_ZONE tz)
std::size_t str_len { 0 };

for (const char *c = str; *c != '\0' && *c != '+'; ++c)
str_len += 1;
str_len += 1;

int year { 0 }, month { 0 }, day { 0 };

Expand Down Expand Up @@ -180,6 +187,21 @@ DateTime::DateTime (const char *s, DT_DATE_STYLE ds, DT_TIME_ZONE tz)
else if (str_len == 22) ms *= 10;
nanosecond_ = ms * 1000000;
}
else if (str_len > 23 && str_len <= 26) {
MicrosecondType micros { 0 };

::sscanf (str, "%d/%d/%d %hu:%hu:%hu.%d",
&month, &day, &year,
&hour_, &minute_, &second_, &micros);
if (str_len <= 24) micros *= 100;
else if (str_len <= 25) micros *= 10;
nanosecond_ = micros * 1000;
}
else if (str_len > 26) {
::sscanf (str, "%d/%d/%d %hu:%hu:%hu.%d",
&month, &day, &year,
&hour_, &minute_, &second_, &nanosecond_);
}
}
else if (ds == DT_DATE_STYLE::EUR_STYLE) {
if (str_len <= 10) {
Expand All @@ -205,6 +227,21 @@ DateTime::DateTime (const char *s, DT_DATE_STYLE ds, DT_TIME_ZONE tz)
else if (str_len == 22) ms *= 10;
nanosecond_ = ms * 1000000;
}
else if (str_len > 23 && str_len <= 26) {
MicrosecondType micros { 0 };

::sscanf (str, "%d/%d/%d %hu:%hu:%hu.%d",
&year, &month, &day,
&hour_, &minute_, &second_, &micros);
if (str_len <= 24) micros *= 100;
else if (str_len <= 25) micros *= 10;
nanosecond_ = micros * 1000;
}
else if (str_len > 26) {
::sscanf (str, "%d/%d/%d %hu:%hu:%hu.%d",
&year, &month, &day,
&hour_, &minute_, &second_, &nanosecond_);
}
}
else if (ds == DT_DATE_STYLE::ISO_STYLE) {
char slug;
Expand Down Expand Up @@ -235,7 +272,7 @@ DateTime::DateTime (const char *s, DT_DATE_STYLE ds, DT_TIME_ZONE tz)
else if (str_len == 22) millis *= 10;
nanosecond_ = millis * 1000000;
}
else if (str_len > 23) {
else if (str_len > 23 && str_len <= 26) {
MicrosecondType micros { 0 };

::sscanf (str, "%d-%d-%d%c%hu:%hu:%hu.%d",
Expand All @@ -245,6 +282,11 @@ DateTime::DateTime (const char *s, DT_DATE_STYLE ds, DT_TIME_ZONE tz)
else if (str_len <= 25) micros *= 10;
nanosecond_ = micros * 1000;
}
else if (str_len > 26) {
::sscanf (str, "%d-%d-%d%c%hu:%hu:%hu.%d",
&year, &month, &day, &slug,
&hour_, &minute_, &second_, &nanosecond_);
}
}
if (year == 0 && month == 0 && day == 0) {
String512 err;
Expand Down Expand Up @@ -448,6 +490,14 @@ bool DateTime::is_us_business_day () const noexcept {
(year () == 2001 && mon == DT_MONTH::SEP && m_day >= 11 &&
m_day <= 14) ||

// Juneteenth holiday
// (June 19 or Monday, June 20 or Friday, June 18)
//
(year() >= 2021 &&
(m_day == 19 || (w_day == DT_WEEKDAY::MON && m_day == 20) ||
(w_day == DT_WEEKDAY::FRI && m_day == 18)) &&
mon == DT_MONTH::JUN) ||

// Martin Luther King Day (third Monday of January)
//
(w_day == DT_WEEKDAY::MON &&
Expand All @@ -466,7 +516,7 @@ bool DateTime::is_us_business_day () const noexcept {
// Independence Day (July 4 or Monday, July 5 or Friday, July 3)
//
((m_day == 4 || (w_day == DT_WEEKDAY::MON && m_day == 5) ||
(w_day == DT_WEEKDAY::FRI && m_day == 3)) &&
(w_day == DT_WEEKDAY::FRI && m_day == 3)) &&
mon == DT_MONTH::JUL) ||

// Labor Day (first Monday of September)
Expand Down
8 changes: 8 additions & 0 deletions test/date_time_tester.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,14 @@ int main (int, char *[]) {

std::cout << "2018-12-21 13:07:35+00 == "
<< dt7.string_format (DT_FORMAT::ISO_DT_TM) << std::endl;

const DateTime dt8("2018-12-21 13:07:35.123456789+00",
DT_DATE_STYLE::ISO_STYLE);
std::string result;

dt8.date_to_str (DT_FORMAT::ISO_DT_NANO, result);
std::cout << "2018-12-21 13:07:35.123456789+00 == " << result
<< std::endl;
}

test_priority_queue();
Expand Down

0 comments on commit f4a37c2

Please sign in to comment.