#include "MAPL_Exceptions.h" ! Test suite ! Not complete ! Some portions are commented out because corresponding procedures to be ! tested are not working completely. module test_MAPL_DateTime_Parsing use MAPL_ExceptionHandling use MAPL_DateTime_Parsing use pfunit use, intrinsic :: iso_fortran_env, only: R64 => real64 implicit none character(len=*), parameter :: DATE_DELIMITER = '-' character(len=*), parameter :: TIME_DELIMITER = ':' integer, dimension(12), parameter :: ENDS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] integer, dimension(size(ENDS)), parameter :: ENDS_LEAP = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] integer, parameter :: MAX_LEN = 1024 integer, parameter :: SUCCESS = _SUCCESS integer, parameter :: FAILURE = _FAILURE contains @test subroutine test_multipleof() @assertTrue(multipleof(21, 7)) @assertFalse(multipleof(22, 7)) @assertTrue(21 .multipleof. 7) @assertFalse(22 .multipleof. 7) end subroutine test_multipleof @test subroutine test_between_op() integer, parameter :: lower = 36 integer, parameter :: upper = 48 integer, parameter :: delta = 6 @assertTrue((lower + delta) .between. [lower, upper]) @assertFalse(lower .between. [lower, upper]) @assertFalse((lower - 1) .between. [lower, upper]) @assertFalse(upper .between. [lower, upper]) @assertFalse((upper + 1) .between. [lower, upper]) end subroutine test_between_op @test subroutine test_in_op() integer, parameter :: lower = 36 integer, parameter :: upper = 48 integer, parameter :: delta = 6 @assertTrue((lower + delta) .between. [lower, upper]) @assertFalse(lower .between. [lower, upper]) @assertFalse((lower - 1) .between. [lower, upper]) @assertFalse(upper .between. [lower, upper]) @assertFalse((upper + 1) .between. [lower, upper]) end subroutine test_in_op @test subroutine test_is_digit() integer :: i integer, parameter :: imin = 0 integer, parameter :: imax = 127 integer, parameter :: i1 = iachar('0') - 1 integer, parameter :: i2 = iachar('9') + 1 integer, parameter :: acodes(*) = [(i, i = imin, i1), (i, i = i2, imax)] integer :: i0 = iachar('0') do i = 0, 9 @assertTrue(is_digit(achar(i0+i))) end do do i = 1, size(acodes) @assertFalse(is_digit(achar(acodes(i)))) end do end subroutine test_is_digit @test subroutine test_is_whole_number() integer :: n do n= 0, 9 @assertTrue(is_whole_number(n)) end do do n= 1, 9 @assertFalse(is_whole_number(-n)) end do end subroutine test_is_whole_number @test subroutine test_get_integer_digit() integer :: n integer, parameter :: NONDIGIT = -1 integer, parameter :: ASCII_MIN = 0 integer, parameter :: ASCII_MAX = 127 integer, parameter :: ASCII_LT0 = iachar('0') - 1 integer, parameter :: ASCII_GT9 = iachar('9') + 1 character(len=10), parameter :: digit = '0123456789' character :: c do n = 1, len(digit) @assertEqual(n-1, get_integer_digit(digit(n:n))) end do do n = ASCII_MIN, ASCII_LT0 c = achar(n) @assertEqual(NONDIGIT, get_integer_digit(c)) end do do n = ASCII_GT9, ASCII_MAX c = achar(n) @assertEqual(NONDIGIT, get_integer_digit(c)) end do end subroutine test_get_integer_digit @test subroutine test_get_integer_digit_from_string integer :: i integer, parameter :: NONDIGIT = -1 character(len=5), parameter :: digit = '19150' integer, dimension(5) :: values = [1, 9, 1, 5, 0] @assertEqual(1, get_integer_digit_from_string('19150', 1)) do i= 1, len(digit) @assertEqual(values(i), get_integer_digit_from_string(digit, i)) end do @assertEqual(NONDIGIT, get_integer_digit_from_string(digit, 0)) @assertEqual(NONDIGIT, get_integer_digit_from_string(digit, -1)) @assertEqual(NONDIGIT, get_integer_digit_from_string(digit, len(digit)+1)) end subroutine test_get_integer_digit_from_string @test subroutine test_read_whole_number() character(len=*), parameter :: NUM_STRING = '01234' integer, parameter :: WHOLE_NUMBER = 1234 integer, parameter :: NOT_WHOLE_NUMBER = -1 character(len=*), parameter :: LETTERS = 'ABCDEFG' character(len=*), parameter :: ALPHA_NUMERICS = '9B4D3F7' character(len=*), parameter :: NEGATIVE_INTEGER = '-' // NUM_STRING character(len=*), parameter :: SYMBOLS = '100%' character(len=*), parameter :: FLOATING_POINT = '10.07' character(len=*), parameter :: POSITIVE_INTEGER = '+' // NUM_STRING @assertEqual(WHOLE_NUMBER, read_whole_number(NUM_STRING)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number(LETTERS)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number(ALPHA_NUMERICS)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number(NEGATIVE_INTEGER)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number(SYMBOLS)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number(FLOATING_POINT)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number(POSITIVE_INTEGER)) end subroutine test_read_whole_number @test subroutine test_read_whole_number_indexed() character(len=11), parameter :: STRING = '12345678901' character(len=15), parameter :: BAD_STRING = '18The3.1415...' integer, parameter :: NOT_WHOLE_NUMBER = -1 @assertEqual(12, read_whole_number_indexed(STRING, 1, 2)) @assertEqual(90, read_whole_number_indexed(STRING, 9, 10)) @assertEqual(7, read_whole_number_indexed(STRING, 7, 7)) @assertEqual(1, read_whole_number_indexed(STRING, 10, 11)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(STRING, 2, 1)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(STRING, 1, 12)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(STRING, -1, 9)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(STRING, 1, -1)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(STRING, 0, 2)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(STRING, 2, 0)) @assertEqual(18, read_whole_number_indexed(BAD_STRING, 1, 2)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(BAD_STRING, 2, 3)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(BAD_STRING, 3, 5)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(BAD_STRING, 5, 5)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(BAD_STRING, 5, 6)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(BAD_STRING, 6, 11)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(BAD_STRING, 7, 7)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed(BAD_STRING, 7, 8)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed('+800', 1, 3)) @assertEqual(NOT_WHOLE_NUMBER, read_whole_number_indexed('-800', 1, 3)) end subroutine test_read_whole_number_indexed @test subroutine test_undelimit() character(len=32), parameter :: UNDELIMITED_DATE = '20220720' character(len=32), parameter :: DATE ='2022-07-20' character(len=32), parameter :: UNDELIMITED_TIME1 = '153437' character(len=32), parameter :: TIME1 = '15:34:37' character(len=32), parameter :: UNDELIMITED_TIME2 = '153437421' character(len=32), parameter :: TIME2 = '15:34:37.421' integer, parameter :: DATEWIDTH = len_trim(UNDELIMITED_DATE) integer, parameter :: TIMEWIDTH1 = len_trim(UNDELIMITED_TIME1) integer, parameter :: TIMEWIDTH2 = len_trim(UNDELIMITED_TIME2) @assertEqual(trim(UNDELIMITED_DATE), trim(undelimit(DATE,'-'))) @assertEqual(DATEWIDTH, len_trim(UNDELIMITED_DATE)) @assertEqual(trim(UNDELIMITED_TIME1), trim(undelimit(TIME1,':'))) @assertEqual(TIMEWIDTH1, len_trim(UNDELIMITED_TIME1)) @assertEqual(trim(UNDELIMITED_TIME2), trim(undelimit(undelimit(TIME2,':'),'.'))) @assertEqual(TIMEWIDTH2, len_trim(UNDELIMITED_TIME2)) @assertTrue(trim(UNDELIMITED_TIME1) /= trim(undelimit(TIME1,'.'))) @assertEqual(trim(UNDELIMITED_TIME1), trim(undelimit(UNDELIMITED_TIME1,':'))) @assertEqual('', trim(undelimit('',':'))) end subroutine test_undelimit @test subroutine test_undelimit_all() character(len=32), parameter :: UNDELIMITED_DATE = '20220720' character(len=32), parameter :: DATE ='2022-07-20' character(len=32), parameter :: UNDELIMITED_TIME1 = '153437' character(len=32), parameter :: TIME1 = '15:34:37' character(len=32), parameter :: UNDELIMITED_TIME2 = '153437421' character(len=32), parameter :: TIME2 = '15:34:37.421' integer, parameter :: DATEWIDTH = len_trim(UNDELIMITED_DATE) integer, parameter :: TIMEWIDTH1 = len_trim(UNDELIMITED_TIME1) integer, parameter :: TIMEWIDTH2 = len_trim(UNDELIMITED_TIME2) character(len=*), parameter :: cf_datetime_string_A = '2023-04-23 21:05:37' character(len=*), parameter :: expected_A = '20230423210537' character(len=*), parameter :: cf_datetime_string_B= '2023-04-23 21:05:37.337' character(len=*), parameter :: expected_B = '20230423210537337' character(len=*), parameter :: undelimited_datetime_string_C = '20230423210537' character(len=*), parameter :: fail_D = '2023-4-23 21:05:37' character(len=*), parameter :: fail_E = '2023-04-23 21:5:37' @assertEqual(trim(UNDELIMITED_DATE), trim(undelimit_all(DATE))) @assertEqual(DATEWIDTH, len_trim(UNDELIMITED_DATE)) @assertEqual(trim(UNDELIMITED_TIME1), trim(undelimit_all(TIME1))) @assertEqual(TIMEWIDTH1, len_trim(UNDELIMITED_TIME1)) @assertEqual(trim(UNDELIMITED_TIME2), trim(undelimit_all(TIME2))) @assertEqual(TIMEWIDTH2, len_trim(UNDELIMITED_TIME2)) @assertEqual(trim(UNDELIMITED_TIME1), trim(undelimit_all(UNDELIMITED_TIME1))) @assertEqual('', trim(undelimit_all(''))) @assertEqual(trim(expected_A), trim(undelimit_all(cf_datetime_string_A)), 'Mismatch A') @assertEqual(trim(expected_B), trim(undelimit_all(cf_datetime_string_B)), 'Mismatch B') @assertEqual(trim(undelimited_datetime_string_C), trim(undelimit_all(undelimited_datetime_string_C)), 'Mismatch C') end subroutine test_undelimit_all @test subroutine test_is_leap_year() @assertTrue(is_leap_year(2024)) @assertFalse(is_leap_year(2023)) @assertFalse(is_leap_year(2022)) @assertFalse(is_leap_year(2021)) @assertFalse(is_leap_year(2100)) @assertTrue(is_leap_year(2000)) end subroutine test_is_leap_year @test subroutine test_get_month_ends() integer, dimension(size(ENDS)) :: actual integer :: i actual = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] actual = get_month_ends(2022) do i = 1, size(actual) @assertEqual(ENDS(i), actual(i)) end do actual = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] actual = get_month_ends(2020) do i = 1, size(actual) @assertEqual(ENDS_LEAP(i), actual(i)) end do end subroutine test_get_month_ends @test subroutine test_get_month_end() integer, parameter :: year = 2022 integer, parameter :: leap_year = 2020 integer :: i do i = 1, 12 @assertEqual(ENDS(i), get_month_end(year, i)) @assertEqual(ENDS_LEAP(i), get_month_end(leap_year, i)) end do end subroutine test_get_month_end @test subroutine test_is_valid_year() integer :: i @assertFalse(is_valid_year(-1)) @assertFalse(is_valid_year(10000)) do i = 0, 9999 @assertTrue(is_valid_year(i)) end do end subroutine test_is_valid_year @test subroutine test_is_valid_month() integer :: i @assertFalse(is_valid_month(0)) @assertFalse(is_valid_month(-1)) @assertFalse(is_valid_month(13)) do i = 1, 12 @assertTrue(is_valid_month(i)) end do end subroutine test_is_valid_month @test subroutine test_is_valid_day() character(len=*), parameter :: FMT = '("day (",i4,", ",i2,", ",i2,")",a)' character(len=*), parameter :: SHOULD = ' should be valid.' character(len=*), parameter :: SHOULD_NOT = ' should not be valid.' character(len=255) :: error_message integer :: d, m, y d = 30; m = 4; y = 2023 write(error_message, fmt=FMT) y, m, d, SHOULD @assertTrue(is_valid_day(y, m, d), trim(error_message)) d = 31 write(error_message, fmt=FMT) y, m, d, SHOULD_NOT @assertFalse(is_valid_day(y, m, d), trim(error_message)) d = 29 write(error_message, fmt=FMT) y, m, d, SHOULD @assertTrue(is_valid_day(y, m, d), trim(error_message)) m = 2 write(error_message, fmt=FMT) y, m, d, SHOULD_NOT @assertFalse(is_valid_day(y, m, d), trim(error_message)) y = 2024 write(error_message, fmt=FMT) y, m, d, SHOULD @assertTrue(is_valid_day(y, m, d), trim(error_message)) end subroutine test_is_valid_day @test subroutine test_is_valid_hour() integer, parameter :: IMIN = 0 integer, parameter :: IMAX = 23 integer :: i do i= IMIN, IMAX @assertTrue(is_valid_hour(i)) end do @assertFalse(is_valid_hour(IMAX+1)) @assertFalse(is_valid_hour(IMIN-1)) end subroutine test_is_valid_hour subroutine test_is_valid_minute() integer, parameter :: IMIN = 0 integer, parameter :: IMAX = 59 integer :: i do i= IMIN, IMAX @assertTrue(is_valid_minute(i)) end do @assertFalse(is_valid_minute(IMAX+1)) @assertFalse(is_valid_minute(IMIN-1)) end subroutine test_is_valid_minute subroutine test_is_valid_second() integer, parameter :: IMIN = 0 integer, parameter :: IMAX = 60 integer :: i do i= IMIN, IMAX @assertTrue(is_valid_second(i)) end do @assertFalse(is_valid_second(IMAX+1)) @assertFalse(is_valid_second(IMIN-1)) end subroutine test_is_valid_second @test subroutine test_is_valid_millisecond() integer, parameter :: IMIN = 0 integer, parameter :: IMAX = 999 integer :: i do i= IMIN, IMAX @assertTrue(is_valid_millisecond(i)) end do @assertFalse(is_valid_millisecond(IMAX+1)) @assertFalse(is_valid_millisecond(IMIN-1)) end subroutine test_is_valid_millisecond @test subroutine test_is_valid_timezone_offset() integer, parameter :: GOOD_TZ = 0 integer, parameter :: BAD_TZ = 60 @assertTrue(is_valid_timezone_offset(0)) @assertTrue(is_valid_timezone_offset(60)) @assertTrue(is_valid_timezone_offset(-60)) @assertFalse(is_valid_timezone_offset(4320)) @assertFalse(is_valid_timezone_offset(-1441)) end subroutine test_is_valid_timezone_offset @test subroutine test_is_valid_date() type(date_fields) :: valid_date type(date_fields) :: invalid_date valid_date = date_fields(2022, 7, 7) invalid_date = date_fields(2022, 6, 31) @assertTrue(is_valid_date(valid_date)) @assertFalse(is_valid_date(invalid_date)) end subroutine test_is_valid_date @test subroutine test_is_valid_time() type(time_fields) :: valid_time type(time_fields) :: invalid_time valid_time = time_fields(9, 41, 33, 456, 0) invalid_time = time_fields(24, 41, 33, 456, 0) @assertTrue(is_valid_time(valid_time)) @assertFalse(is_valid_time(invalid_time)) end subroutine test_is_valid_time @test subroutine test_parse_timezone_offset() integer, parameter :: FIELD_WIDTH = 2 integer, parameter :: INVALID_OFFSET = -1 character(len=*), parameter :: HOUR_ONLY = '15' character(len=*), parameter :: HOUR_MINUTE00 = '1500' character(len=*), parameter :: HOUR_MINUTE = '1530' integer, parameter :: OFFSET1500 = 15*60 integer, parameter :: OFFSET1530 = 15*60 + 30 character(len=*), parameter :: NARROW1 = '1' character(len=*), parameter :: NARROW3 = '153' character(len=*), parameter :: WIDE5 = '15307' character(len=*), parameter :: GARBAGE = '1T3R' character(len=*), parameter :: NEG_HOUR = '-15' character(len=*), parameter :: NEG_HOURMIN00 = '-1500' character(len=*), parameter :: NEG_HOURMIN = '-1530' integer, parameter :: OFFSETM1500 = -1*(15*60) integer, parameter :: OFFSETM1530 = -1*(15*60 + 30) @assertEqual(OFFSET1500, parse_timezone_offset(HOUR_ONLY, FIELD_WIDTH)) @assertEqual(OFFSET1500, parse_timezone_offset(HOUR_MINUTE00, FIELD_WIDTH)) @assertEqual(OFFSET1530, parse_timezone_offset(HOUR_MINUTE, FIELD_WIDTH)) @assertTrue(parse_timezone_offset(NARROW1, FIELD_WIDTH) < 0) @assertTrue(parse_timezone_offset(NARROW3, FIELD_WIDTH) < 0) @assertTrue(parse_timezone_offset(WIDE5, FIELD_WIDTH) < 0) @assertTrue(parse_timezone_offset(GARBAGE, FIELD_WIDTH) < 0) end subroutine test_parse_timezone_offset @test subroutine test_parse_date() type(date_fields) :: date date = parse_date('2022-07-07', DATE_DELIMITER) @assertTrue(date%is_valid_) @assertEqual(2022, date%year_) @assertEqual(7, date%month_) @assertEqual(7, date%day_) date = parse_date('20220707', DATE_DELIMITER) @assertTrue(date%is_valid_) @assertEqual(2022, date%year_) @assertEqual(7, date%month_) @assertEqual(7, date%day_) end subroutine test_parse_date @test subroutine test_parse_time() type(time_fields) :: time time = parse_time('17:41:07.513Z', TIME_DELIMITER) @assertTrue(time%is_valid_) @assertEqual(17, time%hour_) @assertEqual(41, time%minute_) @assertEqual(7, time%second_) @assertEqual(513, time%millisecond_) @assertEqual(0, time%timezone_offset_) time = parse_time('174107.513Z', TIME_DELIMITER) @assertTrue(time%is_valid_) @assertEqual(17, time%hour_) @assertEqual(41, time%minute_) @assertEqual(7, time%second_) @assertEqual(513, time%millisecond_) @assertEqual(0, time%timezone_offset_) end subroutine test_parse_time @test subroutine test_construct_date_fields_null() type(date_fields) :: df df = date_fields() @assertFalse(df % is_valid(), 'null df should not be valid.') end subroutine test_construct_date_fields_null @test subroutine test_construct_time_fields_null() type(time_fields) :: tf tf = time_fields() @assertFalse(tf % is_valid(), 'null tf should not be valid.') end subroutine test_construct_time_fields_null @test subroutine test_get_year_field type(date_fields) :: df integer :: d = 23, m = 4, y = 2023 df = date_fields(y, m, d) @assertTrue(df % is_valid(), 'Failed to initialize df') @assertEqual(y, df % year(), 'Wrong year') end subroutine test_get_year_field @test subroutine test_get_month_field type(date_fields) :: df integer :: d = 23, m = 4, y = 2023 df = date_fields(y, m, d) @assertTrue(df % is_valid(), 'Failed to initialize df') @assertEqual(m, df % month(), 'Wrong month') end subroutine test_get_month_field @test subroutine test_get_day_field type(date_fields) :: df integer :: d = 23, m = 4, y = 2023 df = date_fields(y, m, d) @assertTrue(df % is_valid(), 'Failed to initialize df') @assertEqual(d, df % day(), 'Wrong month') end subroutine test_get_day_field @test subroutine test_are_valid_date_fields type(date_fields) :: df df = date_fields(2023, 4, 25) @assertTrue(df % is_valid(), 'df should be valid.') df = date_fields(2023, 4, 31) @assertFalse(df % is_valid(), 'df should not be valid.') end subroutine test_are_valid_date_fields @test subroutine test_get_hour_field type(time_fields) :: tf integer :: h = 13, m = 43, s = 37, ms = 100, tzo = 0 tf = time_fields(h, m, s, ms, tzo) @assertTrue(tf % is_valid(), 'Failed to initialize tf') @assertEqual(h, tf % hour()) end subroutine test_get_hour_field @test subroutine test_get_minute_field type(time_fields) :: tf integer :: h = 13, m = 43, s = 37, ms = 100, tzo = 0 tf = time_fields(h, m, s, ms, tzo) @assertTrue(tf % is_valid(), 'Failed to initialize tf') @assertEqual(m, tf % minute()) end subroutine test_get_minute_field @test subroutine test_get_second_field type(time_fields) :: tf integer :: h = 13, m = 43, s = 37, ms = 100, tzo = 0 tf = time_fields(h, m, s, ms, tzo) @assertTrue(tf % is_valid(), 'Failed to initialize tf') @assertEqual(s, tf % second()) end subroutine test_get_second_field @test subroutine test_get_millisecond_field type(time_fields) :: tf integer :: h = 13, m = 43, s = 37, ms = 100, tzo = 0 tf = time_fields(h, m, s, ms, tzo) @assertTrue(tf % is_valid(), 'Failed to initialize tf') @assertEqual(ms, tf % millisecond()) end subroutine test_get_millisecond_field @test subroutine test_get_timezone_offset_field type(time_fields) :: tf integer :: h = 13, m = 43, s = 37, ms = 100, tzo = 0 tf = time_fields(h, m, s, ms, tzo) @assertTrue(tf % is_valid(), 'Failed to initialize tf') @assertEqual(tzo, tf % timezone_offset()) end subroutine test_get_timezone_offset_field @test subroutine test_are_valid_time_fields type(time_fields) :: tf tf = time_fields(13, 43, 37, 100, 0) @assertTrue(tf % is_valid(), 'tf should be valid.') tf = time_fields(13, 63, 37, 100, 0) @assertFalse(tf % is_valid(), 'tf should not be valid.') end subroutine test_are_valid_time_fields ! @test subroutine test_convert_to_ISO8601DateTime() character(len=*), parameter :: cf_datetime_string_A = '2023-04-23 21:05:37' character(len=*), parameter :: expected_A = '2023-04-23T21:05:37' character(len=*), parameter :: cf_datetime_string_B= '2023-04-23 21:05:37.337' character(len=*), parameter :: expected_B = '2023-04-23T21:05:37.337' character(len=*), parameter :: undelimited_datetime_string_C = '20230423210537' character(len=*), parameter :: fail_D = '2023-4-23 21:05:37' character(len=*), parameter :: fail_E = '2023-04-23 21:5:37' character(len=:), allocatable :: output character(len=MAX_LEN) :: actual integer :: status call convert_to_ISO8601DateTime(cf_datetime_string_A, output, rc = status) @assertEqual(status, 0, 'Conversion A failed: ' // trim(cf_datetime_string_A)) actual = trim(output) @assertEqual(expected_A, trim(actual), 'Datetime strings do not match.') call convert_to_ISO8601DateTime(cf_datetime_string_B, output, rc = status) @assertEqual(status, 0, 'Conversion B failed: ' // trim(cf_datetime_string_B)) actual = trim(output) @assertEqual(expected_B, trim(actual), 'Datetime strings do not match.') call convert_to_ISO8601DateTime(undelimited_datetime_string_C, output, rc = status) @assertEqual(status, 0, 'Conversion C failed: ' // trim(undelimited_datetime_string_C)) actual = trim(output) @assertEqual(expected_A, trim(actual), 'Datetime strings do not match.') call convert_to_ISO8601DateTime(fail_D, output, rc = status) @assertFalse(status == 0, 'Failed to catch illegal value - D') call convert_to_ISO8601DateTime(fail_E, output, rc = status) @assertFalse(status == 0, 'Failed to catch illegal value - E.') end subroutine test_convert_to_ISO8601DateTime @test subroutine test_construct_datetime_duration() integer, parameter :: IEX = UNSET_FIELD real(kind=R64), parameter :: REX = real(IEX, kind=R64) logical, parameter :: LEX = .FALSE. type(datetime_duration) :: d d = datetime_duration() @assertEqual(IEX, d % year, 'year should be unset') @assertEqual(IEX, d % month, 'month should be unset') @assertEqual(IEX, d % day, 'day should be unset') @assertEqual(IEX, d % hour, 'hour should be unset') @assertEqual(IEX, d % minute, 'minute should be unset') @assertEqual(IEX, d % second, 'second should be unset') @assertEqual(REX, d % hour_real, 'hour_real should be unset') @assertEqual(REX, d % minute_real, 'minute_real should be unset') @assertEqual(REX, d % second_real, 'second_real should be unset') @assertFalse(d % year_is_set(), 'year_is_set should be .FALSE.') @assertFalse(d % month_is_set(), 'month_is_set should be .FALSE.') @assertFalse(d % day_is_set(), 'hour_is_set should be .FALSE.') @assertFalse(d % hour_is_set(), 'hour_is_set should be .FALSE.') @assertFalse(d % minute_is_set(), 'minute_is_set should be .FALSE.') @assertFalse(d % second_is_set(), 'hour_is_set should be .FALSE.') @assertFalse(d % hour_is_real(), 'hour_is_real should be .FALSE.') @assertFalse(d % minute_is_real(), 'minute_is_real should be .FALSE.') @assertFalse(d % second_is_real(), 'hour_is_real should be .FALSE.') end subroutine test_construct_datetime_duration subroutine test_set_year_datetime_duration() type(datetime_duration) :: d integer :: expected expected = 2001 d = datetime_duration() call d % set_year(expected) @assertEqual(expected, d % year, 'Value not set correctly') end subroutine test_set_year_datetime_duration subroutine test_set_month_datetime_duration() type(datetime_duration) :: d integer :: expected expected = 3 d = datetime_duration() call d % set_month(expected) @assertEqual(expected, d % month, 'Value not set correctly') end subroutine test_set_month_datetime_duration subroutine test_set_day_datetime_duration() type(datetime_duration) :: d integer :: expected expected = 20 d = datetime_duration() call d % set_day(expected) @assertEqual(expected, d % day, 'Value not set correctly') end subroutine test_set_day_datetime_duration subroutine test_set_hour_datetime_duration() type(datetime_duration) :: d integer :: expected expected = 3 d = datetime_duration() call d % set_hour(expected) @assertEqual(expected, d % hour, 'Value not set correctly') end subroutine test_set_hour_datetime_duration subroutine test_set_minute_datetime_duration() type(datetime_duration) :: d integer :: expected expected = 10 d = datetime_duration() call d % set_minute(expected) @assertEqual(expected, d % minute, 'Value not set correctly') end subroutine test_set_minute_datetime_duration subroutine test_set_second_datetime_duration() type(datetime_duration) :: d integer :: expected expected = 1800 d = datetime_duration() call d % set_second(expected) @assertEqual(expected, d % second, 'Value not set correctly') end subroutine test_set_second_datetime_duration subroutine test_set_hour_real_datetime_duration() type(datetime_duration) :: d real(R64) :: expected expected = 3.0 d = datetime_duration() call d % set_hour_real(expected) @assertEqual(expected, d % hour_real, 'Value not set correctly') end subroutine test_set_hour_real_datetime_duration subroutine test_set_minute_real_datetime_duration() type(datetime_duration) :: d real(R64) :: expected expected = 10.0 d = datetime_duration() call d % set_minute_real(expected) @assertEqual(expected, d % minute_real, 'Value not set correctly') end subroutine test_set_minute_real_datetime_duration subroutine test_set_second_real_datetime_duration() type(datetime_duration) :: d real(R64) :: expected expected = 1800.0 d = datetime_duration() call d % set_second_real(expected) @assertEqual(expected, d % second_real, 'Value not set correctly') end subroutine test_set_second_real_datetime_duration subroutine test_set_real_value_datetime_duration() type(datetime_duration) :: d real(R64) :: expected expected = 1800.0 d = datetime_duration() call d % set_value(SECOND_TIME_UNIT, expected) @assertEqual(expected, d % second_real, 'Value not set correctly') end subroutine test_set_real_value_datetime_duration subroutine test_set_integer_value_datetime_duration() type(datetime_duration) :: d integer :: expected expected = 1800 d = datetime_duration() call d % set_value(SECOND_TIME_UNIT, expected) @assertEqual(expected, d % second, 'Value not set correctly') end subroutine test_set_integer_value_datetime_duration subroutine test_is_valid_datestring() end subroutine test_is_valid_datestring subroutine test_is_in_char_set() character(len=*), parameter :: DIGITS = '1234567890' character :: ch ch = '0' @assertTrue(is_in_char_set(ch, DIGITS), 'Character not found') ch = 'A' @assertFalse(is_in_char_set(ch, DIGITS), 'Character is not in set') end subroutine test_is_in_char_set subroutine test_find_delta() end subroutine test_find_delta subroutine test_find_delta_datestring() end subroutine test_find_delta_datestring subroutine test_split_digit_string_delimited() end subroutine test_split_digit_string_delimited subroutine test_valid_index() end subroutine test_valid_index subroutine test_split_digit_string_indexed() end subroutine test_split_digit_string_indexed subroutine test_convert_lengths_to_indices() end subroutine test_convert_lengths_to_indices @test subroutine test_get_time_unit() integer(kind(TIME_UNIT)) :: expected, actual character(len=8) :: unit_name unit_name = 'year' expected = YEAR_TIME_UNIT actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = unit_name // 's' actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = 'month' expected = MONTH_TIME_UNIT actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = unit_name // 's' actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = 'day' expected = DAY_TIME_UNIT actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = unit_name // 's' actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = 'hour' expected = HOUR_TIME_UNIT actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = unit_name // 's' actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = 'minute' expected = MINUTE_TIME_UNIT actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = unit_name // 's' actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = 'second' expected = SECOND_TIME_UNIT actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = unit_name // 's' actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) unit_name = 'furlong' expected = UNKNOWN_TIME_UNIT actual = get_time_unit(unit_name) @assertEqual(expected, actual, 'Mismatch for ' // unit_name) end subroutine test_get_time_unit end module test_MAPL_DateTime_Parsing