time: d,c,dd,ddd,dddd pattern support for parse_format() (#22003)

This commit is contained in:
Ivan Vatlin 2024-08-09 10:27:15 +00:00 committed by GitHub
parent 6e2ae7c2ed
commit c0bb9605c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 102 additions and 7 deletions

View File

@ -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 {
@ -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
@ -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')

View File

@ -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])
@ -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

View File

@ -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

View File

@ -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'
}