Skip to content

Commit

Permalink
time: d,c,dd,ddd,dddd pattern support for parse_format() (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffangelion authored Aug 9, 2024
1 parent 6e2ae7c commit c0bb960
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 7 deletions.
60 changes: 55 additions & 5 deletions vlib/time/date_time_parser.v
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,43 @@ fn (mut p DateTimeParser) must_be_valid_three_letter_month() !int {
return error_invalid_time(0, 'invalid three letter month, at: ${p.current_pos_datetime}')
}

fn (mut p DateTimeParser) must_be_valid_week_day(letters int) !string {
val := p.next(letters)!
fn (mut p DateTimeParser) must_be_valid_week_day() !string {
for v in long_days {
if v[0..letters] == val {
return v
if p.current_pos_datetime + v.len < p.datetime.len {
weekday := p.datetime[p.current_pos_datetime..p.current_pos_datetime + v.len]
if v == weekday {
p.current_pos_datetime += v.len
return weekday
}
}
}
return error_invalid_time(0, 'invalid month name, at: ${p.current_pos_datetime}')
return error_invalid_time(0, 'invalid weekday, at: ${p.current_pos_datetime}')
}

fn (mut p DateTimeParser) must_be_valid_two_letter_week_day() !int {
if p.current_pos_datetime + 2 < p.datetime.len {
letters := p.datetime[p.current_pos_datetime..p.current_pos_datetime + 2]
for d := 1; d <= long_days.len; d++ {
if days_string[(d - 1) * 3..d * 3 - 1] == letters {
p.current_pos_datetime += 2
return d
}
}
}
return error_invalid_time(0, 'invalid two letter weekday, at: ${p.current_pos_datetime}')
}

fn (mut p DateTimeParser) must_be_valid_three_letter_week_day() !int {
if p.current_pos_datetime + 3 < p.datetime.len {
letters := p.datetime[p.current_pos_datetime..p.current_pos_datetime + 3]
for d := 1; d <= long_days.len; d++ {
if days_string[(d - 1) * 3..d * 3] == letters {
p.current_pos_datetime += 3
return d
}
}
}
return error_invalid_time(0, 'invalid three letter weekday, at: ${p.current_pos_datetime}')
}

fn extract_tokens(s string) ![]string {
Expand All @@ -133,9 +162,15 @@ fn extract_tokens(s string) ![]string {
// YY - 2 digit year, 00..99
// M - month, 1..12
// MM - month, 2 digits, 01..12
// MMM - month, three letters, Jan..Dec
// MMMM - name of month
// D - day of the month, 1..31
// DD - day of the month, 01..31
// d - day of week, 0..6
// c - day of week, 1..7
// dd - day of week, Su..Sa
// ddd - day of week, Sun..Sat
// dddd - day of week, Sunday..Saturday
// H - hour, 0..23
// HH - hour, 00..23
// h - hour, 0..23
Expand Down Expand Up @@ -206,6 +241,21 @@ fn (mut p DateTimeParser) parse() !Time {
return error_invalid_time(0, 'day must be between 01 and 31')
}
}
'd' {
p.must_be_int(1) or { return err }
}
'c' {
p.must_be_int(1) or { return err }
}
'dd' {
p.must_be_valid_two_letter_week_day() or { return err }
}
'ddd' {
p.must_be_valid_three_letter_week_day() or { return err }
}
'dddd' {
p.must_be_valid_week_day() or { return err }
}
'H' {
hour_ = p.must_be_int_with_minimum_length(1, 2, true) or {
return error_invalid_time(0, 'end of string reached before hours where specified')
Expand Down
4 changes: 2 additions & 2 deletions vlib/time/format.v
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ pub fn (t Time) custom_format(s string) string {
int(is_leap_year(t.year))))
}
'd' {
sb.write_string(t.day_of_week().str())
sb.write_string('${t.day_of_week() % 7}')
}
'dd' {
sb.write_string(long_days[t.day_of_week() - 1][0..2])
Expand Down Expand Up @@ -472,7 +472,7 @@ pub fn (t Time) custom_format(s string) string {
sb.write_string(ordinal_suffix((t.month % 4) + 1))
}
'c' {
sb.write_string('${t.day_of_week() + 1}')
sb.write_string('${t.day_of_week()}')
}
'N' {
// TODO: integrate BC
Expand Down
5 changes: 5 additions & 0 deletions vlib/time/parse.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ pub fn parse(s string) !Time {
// MMMM - name of month
// D - day of the month, 1..31
// DD - day of the month, 01..31
// d - day of week, 0..6
// c - day of week, 1..7
// dd - day of week, Su..Sa
// ddd - day of week, Sun..Sat
// dddd - day of week, Sunday..Saturday
// H - hour, 0..23
// HH - hour, 00..23
// h - hour, 0..23
Expand Down
40 changes: 40 additions & 0 deletions vlib/time/time_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,43 @@ fn test_parse_three_letters_month() {
tm_tm := time.parse_format(tm_s, format)!
assert tm_tm.month == tm.month
}

fn test_parse_ordinal_weekday_d() {
format := 'd MMM DD HH:mm:ss YYYY'
dt := '0 Jan 01 00:00:00 1970'
tm := time.parse_format(dt, format)!
tm_s := tm.custom_format(format)
assert tm_s == '4 Jan 01 00:00:00 1970'
}

fn test_parse_ordinal_weekday_c() {
format := 'c MMM DD HH:mm:ss YYYY'
dt := '7 Jan 01 00:00:00 1970'
tm := time.parse_format(dt, format)!
tm_s := tm.custom_format(format)
assert tm_s == '4 Jan 01 00:00:00 1970'
}

fn test_parse_two_letters_weekday() {
format := 'dd MMM DD HH:mm:ss YYYY'
dt := 'Su Jan 01 00:00:00 1970'
tm := time.parse_format(dt, format)!
tm_s := tm.custom_format(format)
assert tm_s == 'Th Jan 01 00:00:00 1970'
}

fn test_parse_three_letters_weekday() {
format := 'ddd MMM DD HH:mm:ss YYYY'
dt := 'Sun Jan 01 00:00:00 1970'
tm := time.parse_format(dt, format)!
tm_s := tm.custom_format(format)
assert tm_s == 'Thu Jan 01 00:00:00 1970'
}

fn test_parse_weekday() {
format := 'dddd MMM DD HH:mm:ss YYYY'
dt := 'Sunday Jan 01 00:00:00 1970'
tm := time.parse_format(dt, format)!
tm_s := tm.custom_format(format)
assert tm_s == 'Thursday Jan 01 00:00:00 1970'
}

0 comments on commit c0bb960

Please sign in to comment.