diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile index dc4e1b1ad..d60586b75 100644 --- a/tests/hard_coded/Mmakefile +++ b/tests/hard_coded/Mmakefile @@ -792,6 +792,7 @@ ifeq "$(findstring profdeep,$(GRADE))" "" bitwise_uint64 \ bitwise_uint8 \ calendar_basics \ + calendar_date_time_conv \ calendar_init_date \ char_to_string \ clamp_int \ diff --git a/tests/hard_coded/calendar_date_time_conv.exp b/tests/hard_coded/calendar_date_time_conv.exp new file mode 100644 index 000000000..3757903ba --- /dev/null +++ b/tests/hard_coded/calendar_date_time_conv.exp @@ -0,0 +1,224 @@ +=== Testing date_time_from_string/2 with valid inputs === + +date_time_from_string("2024-01-15 12:30:00") ===> TEST PASSED (accepted: date_time(2024, 1, 15, 12, 30, 0, 0)) +date_time_from_string("1977-10-09 12:00:00") ===> TEST PASSED (accepted: date_time(1977, 10, 9, 12, 0, 0, 0)) +date_time_from_string("0000-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(0, 1, 1, 0, 0, 0, 0)) +date_time_from_string("0000-12-31 23:59:59") ===> TEST PASSED (accepted: date_time(0, 12, 31, 23, 59, 59, 0)) +date_time_from_string("0001-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(1, 1, 1, 0, 0, 0, 0)) +date_time_from_string("9999-12-31 23:59:59") ===> TEST PASSED (accepted: date_time(9999, 12, 31, 23, 59, 59, 0)) +date_time_from_string("-0001-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(-1, 1, 1, 0, 0, 0, 0)) +date_time_from_string("-0001-12-31 00:00:00") ===> TEST PASSED (accepted: date_time(-1, 12, 31, 0, 0, 0, 0)) +date_time_from_string("-4713-11-24 00:00:00") ===> TEST PASSED (accepted: date_time(-4713, 11, 24, 0, 0, 0, 0)) +date_time_from_string("10000-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(10000, 1, 1, 0, 0, 0, 0)) +date_time_from_string("100000-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(100000, 1, 1, 0, 0, 0, 0)) +date_time_from_string("2000-02-29 00:00:00") ===> TEST PASSED (accepted: date_time(2000, 2, 29, 0, 0, 0, 0)) +date_time_from_string("2024-02-29 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 2, 29, 0, 0, 0, 0)) +date_time_from_string("0000-02-29 00:00:00") ===> TEST PASSED (accepted: date_time(0, 2, 29, 0, 0, 0, 0)) +date_time_from_string("-0004-02-29 00:00:00") ===> TEST PASSED (accepted: date_time(-4, 2, 29, 0, 0, 0, 0)) +date_time_from_string("2023-02-28 00:00:00") ===> TEST PASSED (accepted: date_time(2023, 2, 28, 0, 0, 0, 0)) +date_time_from_string("1900-02-28 00:00:00") ===> TEST PASSED (accepted: date_time(1900, 2, 28, 0, 0, 0, 0)) +date_time_from_string("2024-01-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 1, 31, 0, 0, 0, 0)) +date_time_from_string("2024-03-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 3, 31, 0, 0, 0, 0)) +date_time_from_string("2024-04-30 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 4, 30, 0, 0, 0, 0)) +date_time_from_string("2024-05-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 5, 31, 0, 0, 0, 0)) +date_time_from_string("2024-06-30 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 6, 30, 0, 0, 0, 0)) +date_time_from_string("2024-07-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 7, 31, 0, 0, 0, 0)) +date_time_from_string("2024-08-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 8, 31, 0, 0, 0, 0)) +date_time_from_string("2024-09-30 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 9, 30, 0, 0, 0, 0)) +date_time_from_string("2024-10-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 10, 31, 0, 0, 0, 0)) +date_time_from_string("2024-11-30 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 11, 30, 0, 0, 0, 0)) +date_time_from_string("2024-12-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 12, 31, 0, 0, 0, 0)) +date_time_from_string("2024-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 0)) +date_time_from_string("2024-01-01 23:59:59") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 23, 59, 59, 0)) +date_time_from_string("2024-01-01 00:00:60") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 60, 0)) +date_time_from_string("2024-01-01 00:00:61") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 61, 0)) +date_time_from_string("2024-01-01 00:00:00.1") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 100000)) +date_time_from_string("2024-01-01 00:00:00.12") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 120000)) +date_time_from_string("2024-01-01 00:00:00.123") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123000)) +date_time_from_string("2024-01-01 00:00:00.1234") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123400)) +date_time_from_string("2024-01-01 00:00:00.12345") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123450)) +date_time_from_string("2024-01-01 00:00:00.123456") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123456)) +date_time_from_string("2024-01-01 00:00:00.000001") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 1)) +date_time_from_string("2024-01-01 00:00:00.999999") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 999999)) +date_time_from_string("2024-12-31 23:59:61.999999") ===> TEST PASSED (accepted: date_time(2024, 12, 31, 23, 59, 61, 999999)) +date_time_from_string("1970-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(1970, 1, 1, 0, 0, 0, 0)) +date_time_from_string("1582-10-15 00:00:00") ===> TEST PASSED (accepted: date_time(1582, 10, 15, 0, 0, 0, 0)) +date_time_from_string("2024-01-01 00:00:00.10") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 100000): to-string: "2024-01-01 00:00:00.1")) +date_time_from_string("2024-01-01 00:00:00.100") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 100000): to-string: "2024-01-01 00:00:00.1")) +date_time_from_string("2024-01-01 00:00:00.1000") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 100000): to-string: "2024-01-01 00:00:00.1")) +date_time_from_string("2024-01-01 00:00:00.10000") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 100000): to-string: "2024-01-01 00:00:00.1")) +date_time_from_string("2024-01-01 00:00:00.100000") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 100000): to-string: "2024-01-01 00:00:00.1")) +date_time_from_string("2024-01-01 00:00:00.120000") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 120000): to-string: "2024-01-01 00:00:00.12")) +date_time_from_string("2024-01-01 00:00:00.123000") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123000): to-string: "2024-01-01 00:00:00.123")) +date_time_from_string("2024-01-01 00:00:00.123400") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123400): to-string: "2024-01-01 00:00:00.1234")) +date_time_from_string("2024-01-01 00:00:00.123450") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123450): to-string: "2024-01-01 00:00:00.12345")) +date_time_from_string("2024-01-01 00:00:00.000000") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 0): to-string: "2024-01-01 00:00:00")) +date_time_from_string("00000-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(0, 1, 1, 0, 0, 0, 0): to-string: "0000-01-01 00:00:00")) +date_time_from_string("00001-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(1, 1, 1, 0, 0, 0, 0): to-string: "0001-01-01 00:00:00")) + +=== Testing date_time_from_string/2 with invalid inputs === + +date_time_from_string("") ===> TEST PASSED (rejected: empty string) +date_time_from_string(" ") ===> TEST PASSED (rejected: blank string) +date_time_from_string("not a date") ===> TEST PASSED (rejected: not a date) +date_time_from_string("2024-01-01") ===> TEST PASSED (rejected: missing time component) +date_time_from_string("12:00:00") ===> TEST PASSED (rejected: missing date component) +date_time_from_string("2024/01/01 00:00:00") ===> TEST PASSED (rejected: incorrect date separator) +date_time_from_string("2024-01-01T00:00:00") ===> TEST PASSED (rejected: ISO 8601 T separator) +date_time_from_string("2024-01-01 00:00") ===> TEST PASSED (rejected: missing seconds) +date_time_from_string("2024-01-01 00:00:00 ") ===> TEST PASSED (rejected: trailing space) +date_time_from_string(" 2024-01-01 00:00:00") ===> TEST PASSED (rejected: leading space) +date_time_from_string("2024-01-01 00:00:00Z") ===> TEST PASSED (rejected: trailing timezone indicator) +date_time_from_string("2024-01-01 00:00:00+10:00") ===> TEST PASSED (rejected: trailing UTC offset) +date_time_from_string("99-01-01 00:00:00") ===> TEST PASSED (rejected: two-digit year) +date_time_from_string("999-01-01 00:00:00") ===> TEST PASSED (rejected: three-digit year) +date_time_from_string("2024-1-01 00:00:00") ===> TEST PASSED (rejected: one-digit month) +date_time_from_string("2024-01-1 00:00:00") ===> TEST PASSED (rejected: one-digit day) +date_time_from_string("2024-01-01 0:00:00") ===> TEST PASSED (rejected: one-digit hour) +date_time_from_string("2024-01-01 00:0:00") ===> TEST PASSED (rejected: one-digit minute) +date_time_from_string("2024-01-01 00:00:0") ===> TEST PASSED (rejected: one-digit second) +date_time_from_string("2024-00-01 00:00:00") ===> TEST PASSED (rejected: month zero) +date_time_from_string("2024-13-01 00:00:00") ===> TEST PASSED (rejected: month 13) +date_time_from_string("2024-01-00 00:00:00") ===> TEST PASSED (rejected: day zero) +date_time_from_string("2024-01-32 00:00:00") ===> TEST PASSED (rejected: day 32 in a 31-day month) +date_time_from_string("2023-02-29 00:00:00") ===> TEST PASSED (rejected: Feb 29 in a non-leap year) +date_time_from_string("1900-02-29 00:00:00") ===> TEST PASSED (rejected: Feb 29 in a century non-leap year) +date_time_from_string("2024-04-31 00:00:00") ===> TEST PASSED (rejected: day 31 in a 30-day month) +date_time_from_string("2024-01-01 24:00:00") ===> TEST PASSED (rejected: hour 24) +date_time_from_string("2024-01-01 00:60:00") ===> TEST PASSED (rejected: minute 60) +date_time_from_string("2024-01-01 00:00:62") ===> TEST PASSED (rejected: second 62) +date_time_from_string("2024-01-01 00:00:00.") ===> TEST PASSED (rejected: trailing dot with no digits) +date_time_from_string("2024-01-01 00:00:00.1234567") ===> TEST PASSED (rejected: seven fractional digits) +date_time_from_string("-01-01 00:00:00") ===> TEST PASSED (rejected: negative sign but only two-digit year) +date_time_from_string("-0001-13-01 00:00:00") ===> TEST PASSED (rejected: negative year with out-of-range month) +date_time_from_string("2024-ab-01 00:00:00") ===> TEST PASSED (rejected: letter in month field) +date_time_from_string("2024-01-01 xx:00:00") ===> TEST PASSED (rejected: letters in hour field) +date_time_from_string("--0001-01-01 00:00:00") ===> TEST PASSED (rejected: double negative prefix) +date_time_from_string("2024--01-01 00:00:00") ===> TEST PASSED (rejected: negative sign on month) +date_time_from_string("2024-01-01 -01:00:00") ===> TEST PASSED (rejected: negative sign on hour) +date_time_from_string("2024-01-01 00:00:-01") ===> TEST PASSED (rejected: negative sign on second) +date_time_from_string("2024-01-01 00:00:00") ===> TEST PASSED (rejected: double space between date and time) +date_time_from_string("2024-01-01 00:00:00.123.456") ===> TEST PASSED (rejected: two decimal points) +date_time_from_string("2024-01-01 00:00:00.123456.7") ===> TEST PASSED (rejected: decimal point in microseconds follow by more) +date_time_from_string("2024-001-01 00:00:00") ===> TEST PASSED (rejected: three-digit month) +date_time_from_string("2024-01-001 00:00:00") ===> TEST PASSED (rejected: three-digit day) +date_time_from_string("2024-01-01 000:00:00") ===> TEST PASSED (rejected: three-digit hour) +date_time_from_string("2024-01-01 00:001:00") ===> TEST PASSED (rejected: three-digit minute) +date_time_from_string("2024-01-01 00:00:001") ===> TEST PASSED (rejected: three-digit second) +date_time_from_string("2024-01-01 00:00:00.0000000") ===> TEST PASSED (rejected: seven zeros in microseconds) +date_time_from_string("2024-01-01 00 :00:00") ===> TEST PASSED (rejected: space within time component) +date_time_from_string("2024 -01-01 00:00:00") ===> TEST PASSED (rejected: space within date component) +date_time_from_string("2024:01:01 00:00:00") ===> TEST PASSED (rejected: colons in date part) +date_time_from_string("2024-01-01 00-00-00") ===> TEST PASSED (rejected: dashes in time part) +date_time_from_string("2024--01 00:00:00") ===> TEST PASSED (rejected: missing month) +date_time_from_string("2024-01- 00:00:00") ===> TEST PASSED (rejected: missing day) +date_time_from_string("2024-01-01 :00:00") ===> TEST PASSED (rejected: missing hour) +date_time_from_string("2024-01-01 00::00") ===> TEST PASSED (rejected: missing minute) +date_time_from_string("2024-01-01 00:00:") ===> TEST PASSED (rejected: trailing colon with no second digits) + +=== Testing det_date_from_string/1 with valid inputs === + +det_date_time_from_string("2024-01-15 12:30:00") ===> TEST PASSED (accepted: date_time(2024, 1, 15, 12, 30, 0, 0)) +det_date_time_from_string("1977-10-09 12:00:00") ===> TEST PASSED (accepted: date_time(1977, 10, 9, 12, 0, 0, 0)) +det_date_time_from_string("0000-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(0, 1, 1, 0, 0, 0, 0)) +det_date_time_from_string("0000-12-31 23:59:59") ===> TEST PASSED (accepted: date_time(0, 12, 31, 23, 59, 59, 0)) +det_date_time_from_string("0001-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(1, 1, 1, 0, 0, 0, 0)) +det_date_time_from_string("9999-12-31 23:59:59") ===> TEST PASSED (accepted: date_time(9999, 12, 31, 23, 59, 59, 0)) +det_date_time_from_string("-0001-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(-1, 1, 1, 0, 0, 0, 0)) +det_date_time_from_string("-0001-12-31 00:00:00") ===> TEST PASSED (accepted: date_time(-1, 12, 31, 0, 0, 0, 0)) +det_date_time_from_string("-4713-11-24 00:00:00") ===> TEST PASSED (accepted: date_time(-4713, 11, 24, 0, 0, 0, 0)) +det_date_time_from_string("10000-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(10000, 1, 1, 0, 0, 0, 0)) +det_date_time_from_string("100000-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(100000, 1, 1, 0, 0, 0, 0)) +det_date_time_from_string("2000-02-29 00:00:00") ===> TEST PASSED (accepted: date_time(2000, 2, 29, 0, 0, 0, 0)) +det_date_time_from_string("2024-02-29 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 2, 29, 0, 0, 0, 0)) +det_date_time_from_string("0000-02-29 00:00:00") ===> TEST PASSED (accepted: date_time(0, 2, 29, 0, 0, 0, 0)) +det_date_time_from_string("-0004-02-29 00:00:00") ===> TEST PASSED (accepted: date_time(-4, 2, 29, 0, 0, 0, 0)) +det_date_time_from_string("2023-02-28 00:00:00") ===> TEST PASSED (accepted: date_time(2023, 2, 28, 0, 0, 0, 0)) +det_date_time_from_string("1900-02-28 00:00:00") ===> TEST PASSED (accepted: date_time(1900, 2, 28, 0, 0, 0, 0)) +det_date_time_from_string("2024-01-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 1, 31, 0, 0, 0, 0)) +det_date_time_from_string("2024-03-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 3, 31, 0, 0, 0, 0)) +det_date_time_from_string("2024-04-30 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 4, 30, 0, 0, 0, 0)) +det_date_time_from_string("2024-05-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 5, 31, 0, 0, 0, 0)) +det_date_time_from_string("2024-06-30 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 6, 30, 0, 0, 0, 0)) +det_date_time_from_string("2024-07-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 7, 31, 0, 0, 0, 0)) +det_date_time_from_string("2024-08-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 8, 31, 0, 0, 0, 0)) +det_date_time_from_string("2024-09-30 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 9, 30, 0, 0, 0, 0)) +det_date_time_from_string("2024-10-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 10, 31, 0, 0, 0, 0)) +det_date_time_from_string("2024-11-30 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 11, 30, 0, 0, 0, 0)) +det_date_time_from_string("2024-12-31 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 12, 31, 0, 0, 0, 0)) +det_date_time_from_string("2024-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 0)) +det_date_time_from_string("2024-01-01 23:59:59") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 23, 59, 59, 0)) +det_date_time_from_string("2024-01-01 00:00:60") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 60, 0)) +det_date_time_from_string("2024-01-01 00:00:61") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 61, 0)) +det_date_time_from_string("2024-01-01 00:00:00.1") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 100000)) +det_date_time_from_string("2024-01-01 00:00:00.12") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 120000)) +det_date_time_from_string("2024-01-01 00:00:00.123") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123000)) +det_date_time_from_string("2024-01-01 00:00:00.1234") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123400)) +det_date_time_from_string("2024-01-01 00:00:00.12345") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123450)) +det_date_time_from_string("2024-01-01 00:00:00.123456") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 123456)) +det_date_time_from_string("2024-01-01 00:00:00.000001") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 1)) +det_date_time_from_string("2024-01-01 00:00:00.999999") ===> TEST PASSED (accepted: date_time(2024, 1, 1, 0, 0, 0, 999999)) +det_date_time_from_string("2024-12-31 23:59:61.999999") ===> TEST PASSED (accepted: date_time(2024, 12, 31, 23, 59, 61, 999999)) +det_date_time_from_string("1970-01-01 00:00:00") ===> TEST PASSED (accepted: date_time(1970, 1, 1, 0, 0, 0, 0)) +det_date_time_from_string("1582-10-15 00:00:00") ===> TEST PASSED (accepted: date_time(1582, 10, 15, 0, 0, 0, 0)) + +=== Testing det_date_from_string/1 with invalid inputs === + +det_date_time_from_string("") ===> TEST PASSED (exception: empty string) +det_date_time_from_string(" ") ===> TEST PASSED (exception: blank string) +det_date_time_from_string("not a date") ===> TEST PASSED (exception: not a date) +det_date_time_from_string("2024-01-01") ===> TEST PASSED (exception: missing time component) +det_date_time_from_string("12:00:00") ===> TEST PASSED (exception: missing date component) +det_date_time_from_string("2024/01/01 00:00:00") ===> TEST PASSED (exception: incorrect date separator) +det_date_time_from_string("2024-01-01T00:00:00") ===> TEST PASSED (exception: ISO 8601 T separator) +det_date_time_from_string("2024-01-01 00:00") ===> TEST PASSED (exception: missing seconds) +det_date_time_from_string("2024-01-01 00:00:00 ") ===> TEST PASSED (exception: trailing space) +det_date_time_from_string(" 2024-01-01 00:00:00") ===> TEST PASSED (exception: leading space) +det_date_time_from_string("2024-01-01 00:00:00Z") ===> TEST PASSED (exception: trailing timezone indicator) +det_date_time_from_string("2024-01-01 00:00:00+10:00") ===> TEST PASSED (exception: trailing UTC offset) +det_date_time_from_string("99-01-01 00:00:00") ===> TEST PASSED (exception: two-digit year) +det_date_time_from_string("999-01-01 00:00:00") ===> TEST PASSED (exception: three-digit year) +det_date_time_from_string("2024-1-01 00:00:00") ===> TEST PASSED (exception: one-digit month) +det_date_time_from_string("2024-01-1 00:00:00") ===> TEST PASSED (exception: one-digit day) +det_date_time_from_string("2024-01-01 0:00:00") ===> TEST PASSED (exception: one-digit hour) +det_date_time_from_string("2024-01-01 00:0:00") ===> TEST PASSED (exception: one-digit minute) +det_date_time_from_string("2024-01-01 00:00:0") ===> TEST PASSED (exception: one-digit second) +det_date_time_from_string("2024-00-01 00:00:00") ===> TEST PASSED (exception: month zero) +det_date_time_from_string("2024-13-01 00:00:00") ===> TEST PASSED (exception: month 13) +det_date_time_from_string("2024-01-00 00:00:00") ===> TEST PASSED (exception: day zero) +det_date_time_from_string("2024-01-32 00:00:00") ===> TEST PASSED (exception: day 32 in a 31-day month) +det_date_time_from_string("2023-02-29 00:00:00") ===> TEST PASSED (exception: Feb 29 in a non-leap year) +det_date_time_from_string("1900-02-29 00:00:00") ===> TEST PASSED (exception: Feb 29 in a century non-leap year) +det_date_time_from_string("2024-04-31 00:00:00") ===> TEST PASSED (exception: day 31 in a 30-day month) +det_date_time_from_string("2024-01-01 24:00:00") ===> TEST PASSED (exception: hour 24) +det_date_time_from_string("2024-01-01 00:60:00") ===> TEST PASSED (exception: minute 60) +det_date_time_from_string("2024-01-01 00:00:62") ===> TEST PASSED (exception: second 62) +det_date_time_from_string("2024-01-01 00:00:00.") ===> TEST PASSED (exception: trailing dot with no digits) +det_date_time_from_string("2024-01-01 00:00:00.1234567") ===> TEST PASSED (exception: seven fractional digits) +det_date_time_from_string("-01-01 00:00:00") ===> TEST PASSED (exception: negative sign but only two-digit year) +det_date_time_from_string("-0001-13-01 00:00:00") ===> TEST PASSED (exception: negative year with out-of-range month) +det_date_time_from_string("2024-ab-01 00:00:00") ===> TEST PASSED (exception: letter in month field) +det_date_time_from_string("2024-01-01 xx:00:00") ===> TEST PASSED (exception: letters in hour field) +det_date_time_from_string("--0001-01-01 00:00:00") ===> TEST PASSED (exception: double negative prefix) +det_date_time_from_string("2024--01-01 00:00:00") ===> TEST PASSED (exception: negative sign on month) +det_date_time_from_string("2024-01-01 -01:00:00") ===> TEST PASSED (exception: negative sign on hour) +det_date_time_from_string("2024-01-01 00:00:-01") ===> TEST PASSED (exception: negative sign on second) +det_date_time_from_string("2024-01-01 00:00:00") ===> TEST PASSED (exception: double space between date and time) +det_date_time_from_string("2024-01-01 00:00:00.123.456") ===> TEST PASSED (exception: two decimal points) +det_date_time_from_string("2024-01-01 00:00:00.123456.7") ===> TEST PASSED (exception: decimal point in microseconds follow by more) +det_date_time_from_string("2024-001-01 00:00:00") ===> TEST PASSED (exception: three-digit month) +det_date_time_from_string("2024-01-001 00:00:00") ===> TEST PASSED (exception: three-digit day) +det_date_time_from_string("2024-01-01 000:00:00") ===> TEST PASSED (exception: three-digit hour) +det_date_time_from_string("2024-01-01 00:001:00") ===> TEST PASSED (exception: three-digit minute) +det_date_time_from_string("2024-01-01 00:00:001") ===> TEST PASSED (exception: three-digit second) +det_date_time_from_string("2024-01-01 00:00:00.0000000") ===> TEST PASSED (exception: seven zeros in microseconds) +det_date_time_from_string("2024-01-01 00 :00:00") ===> TEST PASSED (exception: space within time component) +det_date_time_from_string("2024 -01-01 00:00:00") ===> TEST PASSED (exception: space within date component) +det_date_time_from_string("2024:01:01 00:00:00") ===> TEST PASSED (exception: colons in date part) +det_date_time_from_string("2024-01-01 00-00-00") ===> TEST PASSED (exception: dashes in time part) +det_date_time_from_string("2024--01 00:00:00") ===> TEST PASSED (exception: missing month) +det_date_time_from_string("2024-01- 00:00:00") ===> TEST PASSED (exception: missing day) +det_date_time_from_string("2024-01-01 :00:00") ===> TEST PASSED (exception: missing hour) +det_date_time_from_string("2024-01-01 00::00") ===> TEST PASSED (exception: missing minute) +det_date_time_from_string("2024-01-01 00:00:") ===> TEST PASSED (exception: trailing colon with no second digits) + diff --git a/tests/hard_coded/calendar_date_time_conv.m b/tests/hard_coded/calendar_date_time_conv.m new file mode 100644 index 000000000..b680be6a8 --- /dev/null +++ b/tests/hard_coded/calendar_date_time_conv.m @@ -0,0 +1,338 @@ +%---------------------------------------------------------------------------% +% vim: ft=mercury ts=4 sw=4 et +%---------------------------------------------------------------------------% +% +% Test predicates and functions from the calendar module that convert +% date_times to and from strings. +% +%---------------------------------------------------------------------------% + +:- module calendar_date_time_conv. +:- interface. + +:- import_module io. + +:- pred main(io::di, io::uo) is cc_multi. + +%---------------------------------------------------------------------------% +%---------------------------------------------------------------------------% + +:- implementation. + +:- import_module bool. +:- import_module calendar. +:- import_module list. +:- import_module string. + +%---------------------------------------------------------------------------% + +main(!IO) :- + test_valid_date_times(!IO), + test_invalid_date_times(!IO), + test_exception_valid_date_times(!IO), + test_exception_invalid_date_times(!IO). + +%---------------------------------------------------------------------------% + +:- pred test_valid_date_times(io::di, io::uo) is det. + +test_valid_date_times(!IO) :- + io.write_string( + "=== Testing date_time_from_string/2 with valid inputs ===\n\n", + !IO), + list.foldl(do_test_valid_date_time(yes), valid_date_times, !IO), + list.foldl(do_test_valid_date_time(no), valid_no_roundtrip_date_times, + !IO), + io.nl(!IO). + +:- pred do_test_valid_date_time(bool::in, dt_conv_test::in, + io::di, io::uo) is det. + +do_test_valid_date_time(CheckRoundTrip, Test, !IO) :- + Test = dt_conv_test(Desc, TestString), + io.format("date_time_from_string(\"%s\") ===> ", [s(TestString)], !IO), + ( if date_time_from_string(TestString, DateTime) then + RoundTripString = date_time_to_string(DateTime), + ( + CheckRoundTrip = yes, + ( if TestString = RoundTripString then + io.format("TEST PASSED (accepted: %s)\n", + [s(string(DateTime))], !IO) + else + io.write_string("TEST FAILED (roundtrip failed)\n", !IO) + ) + ; + CheckRoundTrip = no, + io.format("TEST PASSED (accepted: %s: to-string: \"%s\"))\n", + [s(string(DateTime)), s(RoundTripString)], !IO) + ) + else + io.format("TEST FAILED (rejected: %s)\n", [s(Desc)], !IO) + ). + +%---------------------------------------------------------------------------% + +:- pred test_invalid_date_times(io::di, io::uo) is det. + +test_invalid_date_times(!IO) :- + io.write_string( + "=== Testing date_time_from_string/2 with invalid inputs ===\n\n", + !IO), + list.foldl(do_test_invalid_date_time, invalid_date_times, !IO), + io.nl(!IO). + +:- pred do_test_invalid_date_time(dt_conv_test::in, io::di, io::uo) is det. + +do_test_invalid_date_time(Test, !IO) :- + Test = dt_conv_test(Desc, TestString), + io.format("date_time_from_string(\"%s\") ===> ", [s(TestString)], !IO), + ( if date_time_from_string(TestString, DateTime) then + DateTimeString = date_time_to_string(DateTime), + io.format("TEST FAILED (accepted: %s)\n", + [s(DateTimeString)], !IO) + else + io.format("TEST PASSED (rejected: %s)\n", [s(Desc)], !IO) + ). + +%---------------------------------------------------------------------------% + +:- pred test_exception_valid_date_times(io::di, io::uo) is cc_multi. + +test_exception_valid_date_times(!IO) :- + io.write_string( + "=== Testing det_date_from_string/1 with valid inputs ===\n\n", !IO), + list.foldl(do_test_exception_valid_date_time, valid_date_times, !IO), + io.nl(!IO). + +:- pred do_test_exception_valid_date_time(dt_conv_test::in, io::di, io::uo) + is cc_multi. + +do_test_exception_valid_date_time(Test, !IO) :- + Test = dt_conv_test(Desc, TestString), + io.format("det_date_time_from_string(\"%s\") ===> ", [s(TestString)], !IO), + ( try [] + DateTime = det_date_time_from_string(TestString) + then + io.format("TEST PASSED (accepted: %s)\n", + [s(string(DateTime))], !IO) + catch_any _ -> + io.format("TEST FAILED (exception: %s)\n", [s(Desc)], !IO) + ). + +%---------------------------------------------------------------------------% + +:- pred test_exception_invalid_date_times(io::di, io::uo) is cc_multi. + +test_exception_invalid_date_times(!IO) :- + io.write_string( + "=== Testing det_date_from_string/1 with invalid inputs ===\n\n", !IO), + list.foldl(do_test_exception_invalid_date_time, invalid_date_times, !IO), + io.nl(!IO). + +:- pred do_test_exception_invalid_date_time(dt_conv_test::in, io::di, io::uo) + is cc_multi. + +do_test_exception_invalid_date_time(Test, !IO) :- + Test = dt_conv_test(Desc, TestString), + io.format("det_date_time_from_string(\"%s\") ===> ", [s(TestString)], !IO), + ( try [] + DateTime = det_date_time_from_string(TestString) + then + io.format("TEST FAILED (accepted: %s)\n", + [s(string(DateTime))], !IO) + catch_any _ -> + io.format("TEST PASSED (exception: %s)\n", [s(Desc)], !IO) + ). + +%---------------------------------------------------------------------------% + +:- type dt_conv_test + ---> dt_conv_test( + description :: string, + test_string :: string + ). + +%---------------------------------------------------------------------------% + +% Valid date_times crated from strings are mostly round-trippable through +% date_time_to_string/1. The only exceptions are where the year components +% have leading zeros or the fractional components have trailing zeros. + + % These can be round-tripped through date_time_to_string/1. + % +:- func valid_date_times = list(dt_conv_test). + +valid_date_times = [ + dt_conv_test("unremarkable mid-month date", "2024-01-15 12:30:00"), + dt_conv_test("arbitrary date in the past", "1977-10-09 12:00:00"), + + dt_conv_test("first day of year zero", "0000-01-01 00:00:00"), + dt_conv_test("last day of year zero", "0000-12-31 23:59:59"), + dt_conv_test("first day of year one", "0001-01-01 00:00:00"), + dt_conv_test("last four-digit year", "9999-12-31 23:59:59"), + + dt_conv_test("year -1", "-0001-01-01 00:00:00"), + dt_conv_test("end of year -1", "-0001-12-31 00:00:00"), + dt_conv_test("Julian period origin in proleptic Gregorian calendar", + "-4713-11-24 00:00:00"), + + dt_conv_test("five-digit year", "10000-01-01 00:00:00"), + dt_conv_test("six-digit year", "100000-01-01 00:00:00"), + + dt_conv_test("400-year leap year", "2000-02-29 00:00:00"), + dt_conv_test("ordinary leap year", "2024-02-29 00:00:00"), + dt_conv_test("year zero is a leap year", "0000-02-29 00:00:00"), + dt_conv_test("negative leap year", "-0004-02-29 00:00:00"), + + dt_conv_test("last day of Feb in a non-leap year", + "2023-02-28 00:00:00"), + dt_conv_test("last day of Feb in a century non-leap year", + "1900-02-28 00:00:00"), + + dt_conv_test("end of Jan", "2024-01-31 00:00:00"), + dt_conv_test("end of March", "2024-03-31 00:00:00"), + dt_conv_test("end of April", "2024-04-30 00:00:00"), + dt_conv_test("end of May", "2024-05-31 00:00:00"), + dt_conv_test("end of June", "2024-06-30 00:00:00"), + dt_conv_test("end of July", "2024-07-31 00:00:00"), + dt_conv_test("end of Aug", "2024-08-31 00:00:00"), + dt_conv_test("end of Sep", "2024-09-30 00:00:00"), + dt_conv_test("end of Oct", "2024-10-31 00:00:00"), + dt_conv_test("end of Nov", "2024-11-30 00:00:00"), + dt_conv_test("end of Dec", "2024-12-31 00:00:00"), + + dt_conv_test("midnight", "2024-01-01 00:00:00"), + dt_conv_test("last second of the day", "2024-01-01 23:59:59"), + dt_conv_test("leap second", "2024-01-01 00:00:60"), + dt_conv_test("double leap second", "2024-01-01 00:00:61"), + + dt_conv_test("one fractional digit", "2024-01-01 00:00:00.1"), + dt_conv_test("two fractional digits", "2024-01-01 00:00:00.12"), + dt_conv_test("three fractional digits", "2024-01-01 00:00:00.123"), + dt_conv_test("four fractional digits", "2024-01-01 00:00:00.1234"), + dt_conv_test("five fractional digits", "2024-01-01 00:00:00.12345"), + dt_conv_test("six fractional digits", "2024-01-01 00:00:00.123456"), + dt_conv_test("smallest nonzero microsecond", "2024-01-01 00:00:00.000001"), + dt_conv_test("largest microsecond value", "2024-01-01 00:00:00.999999"), + + dt_conv_test("all maximum", "2024-12-31 23:59:61.999999"), + dt_conv_test("Unix epoch", "1970-01-01 00:00:00"), + dt_conv_test("first day of the Gregorian calendar", + "1582-10-15 00:00:00") +]. + + % These cannot be round-tripped through date_time_to_string/1. + % +:- func valid_no_roundtrip_date_times = list(dt_conv_test). + +valid_no_roundtrip_date_times =[ + dt_conv_test("one fractional trailing zero", "2024-01-01 00:00:00.10"), + dt_conv_test("two fractional trailing zeros", "2024-01-01 00:00:00.100"), + dt_conv_test("three fractional trailing zeros", + "2024-01-01 00:00:00.1000"), + dt_conv_test("four fractional trailing zeros", + "2024-01-01 00:00:00.10000"), + dt_conv_test("five fractional trailing zeros", + "2024-01-01 00:00:00.100000"), + + dt_conv_test("trailing zeros after two fractional digits", + "2024-01-01 00:00:00.120000"), + dt_conv_test("trailing zeros after three fractional digits", + "2024-01-01 00:00:00.123000"), + dt_conv_test("trailing zeros after four fractional digits", + "2024-01-01 00:00:00.123400"), + dt_conv_test("trailing zeros after five fractional digits", + "2024-01-01 00:00:00.123450"), + + dt_conv_test("all zero fractional digits", + "2024-01-01 00:00:00.000000"), + + dt_conv_test("five digit year zero", "00000-01-01 00:00:00"), + dt_conv_test("five digit year one", "00001-01-01 00:00:00") +]. + +%---------------------------------------------------------------------------% + +:- func invalid_date_times = list(dt_conv_test). + +invalid_date_times = [ + dt_conv_test("empty string", ""), + dt_conv_test("blank string", " "), + dt_conv_test("not a date", "not a date"), + dt_conv_test("missing time component", "2024-01-01"), + dt_conv_test("missing date component", "12:00:00"), + dt_conv_test("incorrect date separator", "2024/01/01 00:00:00"), + dt_conv_test("ISO 8601 T separator", "2024-01-01T00:00:00"), + dt_conv_test("missing seconds", "2024-01-01 00:00"), + dt_conv_test("trailing space", "2024-01-01 00:00:00 "), + dt_conv_test("leading space", " 2024-01-01 00:00:00"), + dt_conv_test("trailing timezone indicator", "2024-01-01 00:00:00Z"), + dt_conv_test("trailing UTC offset", "2024-01-01 00:00:00+10:00"), + + dt_conv_test("two-digit year", "99-01-01 00:00:00"), + dt_conv_test("three-digit year", "999-01-01 00:00:00"), + + dt_conv_test("one-digit month", "2024-1-01 00:00:00"), + dt_conv_test("one-digit day", "2024-01-1 00:00:00"), + dt_conv_test("one-digit hour", "2024-01-01 0:00:00"), + dt_conv_test("one-digit minute", "2024-01-01 00:0:00"), + dt_conv_test("one-digit second", "2024-01-01 00:00:0"), + + dt_conv_test("month zero", "2024-00-01 00:00:00"), + dt_conv_test("month 13", "2024-13-01 00:00:00"), + dt_conv_test("day zero", "2024-01-00 00:00:00"), + dt_conv_test("day 32 in a 31-day month", "2024-01-32 00:00:00"), + dt_conv_test("Feb 29 in a non-leap year", "2023-02-29 00:00:00"), + dt_conv_test("Feb 29 in a century non-leap year", "1900-02-29 00:00:00"), + dt_conv_test("day 31 in a 30-day month", "2024-04-31 00:00:00"), + dt_conv_test("hour 24", "2024-01-01 24:00:00"), + dt_conv_test("minute 60", "2024-01-01 00:60:00"), + dt_conv_test("second 62", "2024-01-01 00:00:62"), + + dt_conv_test("trailing dot with no digits", "2024-01-01 00:00:00."), + dt_conv_test("seven fractional digits", "2024-01-01 00:00:00.1234567"), + + dt_conv_test("negative sign but only two-digit year", + "-01-01 00:00:00"), + dt_conv_test("negative year with out-of-range month", + "-0001-13-01 00:00:00"), + + dt_conv_test("letter in month field", "2024-ab-01 00:00:00"), + dt_conv_test("letters in hour field", "2024-01-01 xx:00:00"), + + dt_conv_test("double negative prefix", "--0001-01-01 00:00:00"), + dt_conv_test("negative sign on month", "2024--01-01 00:00:00"), + dt_conv_test("negative sign on hour", "2024-01-01 -01:00:00"), + dt_conv_test("negative sign on second", "2024-01-01 00:00:-01"), + + dt_conv_test("double space between date and time", + "2024-01-01 00:00:00"), + dt_conv_test("two decimal points", "2024-01-01 00:00:00.123.456"), + dt_conv_test("decimal point in microseconds follow by more", + "2024-01-01 00:00:00.123456.7"), + dt_conv_test("three-digit month", "2024-001-01 00:00:00"), + dt_conv_test("three-digit day", "2024-01-001 00:00:00"), + dt_conv_test("three-digit hour", "2024-01-01 000:00:00"), + dt_conv_test("three-digit minute", "2024-01-01 00:001:00"), + dt_conv_test("three-digit second", "2024-01-01 00:00:001"), + + dt_conv_test("seven zeros in microseconds", + "2024-01-01 00:00:00.0000000"), + + dt_conv_test("space within time component", "2024-01-01 00 :00:00"), + dt_conv_test("space within date component", "2024 -01-01 00:00:00"), + + dt_conv_test("colons in date part", "2024:01:01 00:00:00"), + dt_conv_test("dashes in time part", "2024-01-01 00-00-00"), + + dt_conv_test("missing month", "2024--01 00:00:00"), + dt_conv_test("missing day", "2024-01- 00:00:00"), + dt_conv_test("missing hour", "2024-01-01 :00:00"), + dt_conv_test("missing minute", "2024-01-01 00::00"), + dt_conv_test("trailing colon with no second digits", + "2024-01-01 00:00:") +]. + +%---------------------------------------------------------------------------% +:- end_module calendar_date_time_conv. +%---------------------------------------------------------------------------%