Skip to content

Commit c0bb960

Browse files
authored
time: d,c,dd,ddd,dddd pattern support for parse_format() (#22003)
1 parent 6e2ae7c commit c0bb960

File tree

4 files changed

+102
-7
lines changed

4 files changed

+102
-7
lines changed

vlib/time/date_time_parser.v

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,43 @@ fn (mut p DateTimeParser) must_be_valid_three_letter_month() !int {
101101
return error_invalid_time(0, 'invalid three letter month, at: ${p.current_pos_datetime}')
102102
}
103103

104-
fn (mut p DateTimeParser) must_be_valid_week_day(letters int) !string {
105-
val := p.next(letters)!
104+
fn (mut p DateTimeParser) must_be_valid_week_day() !string {
106105
for v in long_days {
107-
if v[0..letters] == val {
108-
return v
106+
if p.current_pos_datetime + v.len < p.datetime.len {
107+
weekday := p.datetime[p.current_pos_datetime..p.current_pos_datetime + v.len]
108+
if v == weekday {
109+
p.current_pos_datetime += v.len
110+
return weekday
111+
}
109112
}
110113
}
111-
return error_invalid_time(0, 'invalid month name, at: ${p.current_pos_datetime}')
114+
return error_invalid_time(0, 'invalid weekday, at: ${p.current_pos_datetime}')
115+
}
116+
117+
fn (mut p DateTimeParser) must_be_valid_two_letter_week_day() !int {
118+
if p.current_pos_datetime + 2 < p.datetime.len {
119+
letters := p.datetime[p.current_pos_datetime..p.current_pos_datetime + 2]
120+
for d := 1; d <= long_days.len; d++ {
121+
if days_string[(d - 1) * 3..d * 3 - 1] == letters {
122+
p.current_pos_datetime += 2
123+
return d
124+
}
125+
}
126+
}
127+
return error_invalid_time(0, 'invalid two letter weekday, at: ${p.current_pos_datetime}')
128+
}
129+
130+
fn (mut p DateTimeParser) must_be_valid_three_letter_week_day() !int {
131+
if p.current_pos_datetime + 3 < p.datetime.len {
132+
letters := p.datetime[p.current_pos_datetime..p.current_pos_datetime + 3]
133+
for d := 1; d <= long_days.len; d++ {
134+
if days_string[(d - 1) * 3..d * 3] == letters {
135+
p.current_pos_datetime += 3
136+
return d
137+
}
138+
}
139+
}
140+
return error_invalid_time(0, 'invalid three letter weekday, at: ${p.current_pos_datetime}')
112141
}
113142

114143
fn extract_tokens(s string) ![]string {
@@ -133,9 +162,15 @@ fn extract_tokens(s string) ![]string {
133162
// YY - 2 digit year, 00..99
134163
// M - month, 1..12
135164
// MM - month, 2 digits, 01..12
165+
// MMM - month, three letters, Jan..Dec
136166
// MMMM - name of month
137167
// D - day of the month, 1..31
138168
// DD - day of the month, 01..31
169+
// d - day of week, 0..6
170+
// c - day of week, 1..7
171+
// dd - day of week, Su..Sa
172+
// ddd - day of week, Sun..Sat
173+
// dddd - day of week, Sunday..Saturday
139174
// H - hour, 0..23
140175
// HH - hour, 00..23
141176
// h - hour, 0..23
@@ -206,6 +241,21 @@ fn (mut p DateTimeParser) parse() !Time {
206241
return error_invalid_time(0, 'day must be between 01 and 31')
207242
}
208243
}
244+
'd' {
245+
p.must_be_int(1) or { return err }
246+
}
247+
'c' {
248+
p.must_be_int(1) or { return err }
249+
}
250+
'dd' {
251+
p.must_be_valid_two_letter_week_day() or { return err }
252+
}
253+
'ddd' {
254+
p.must_be_valid_three_letter_week_day() or { return err }
255+
}
256+
'dddd' {
257+
p.must_be_valid_week_day() or { return err }
258+
}
209259
'H' {
210260
hour_ = p.must_be_int_with_minimum_length(1, 2, true) or {
211261
return error_invalid_time(0, 'end of string reached before hours where specified')

vlib/time/format.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ pub fn (t Time) custom_format(s string) string {
393393
int(is_leap_year(t.year))))
394394
}
395395
'd' {
396-
sb.write_string(t.day_of_week().str())
396+
sb.write_string('${t.day_of_week() % 7}')
397397
}
398398
'dd' {
399399
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 {
472472
sb.write_string(ordinal_suffix((t.month % 4) + 1))
473473
}
474474
'c' {
475-
sb.write_string('${t.day_of_week() + 1}')
475+
sb.write_string('${t.day_of_week()}')
476476
}
477477
'N' {
478478
// TODO: integrate BC

vlib/time/parse.c.v

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ pub fn parse(s string) !Time {
139139
// MMMM - name of month
140140
// D - day of the month, 1..31
141141
// DD - day of the month, 01..31
142+
// d - day of week, 0..6
143+
// c - day of week, 1..7
144+
// dd - day of week, Su..Sa
145+
// ddd - day of week, Sun..Sat
146+
// dddd - day of week, Sunday..Saturday
142147
// H - hour, 0..23
143148
// HH - hour, 00..23
144149
// h - hour, 0..23

vlib/time/time_test.v

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,3 +396,43 @@ fn test_parse_three_letters_month() {
396396
tm_tm := time.parse_format(tm_s, format)!
397397
assert tm_tm.month == tm.month
398398
}
399+
400+
fn test_parse_ordinal_weekday_d() {
401+
format := 'd MMM DD HH:mm:ss YYYY'
402+
dt := '0 Jan 01 00:00:00 1970'
403+
tm := time.parse_format(dt, format)!
404+
tm_s := tm.custom_format(format)
405+
assert tm_s == '4 Jan 01 00:00:00 1970'
406+
}
407+
408+
fn test_parse_ordinal_weekday_c() {
409+
format := 'c MMM DD HH:mm:ss YYYY'
410+
dt := '7 Jan 01 00:00:00 1970'
411+
tm := time.parse_format(dt, format)!
412+
tm_s := tm.custom_format(format)
413+
assert tm_s == '4 Jan 01 00:00:00 1970'
414+
}
415+
416+
fn test_parse_two_letters_weekday() {
417+
format := 'dd MMM DD HH:mm:ss YYYY'
418+
dt := 'Su Jan 01 00:00:00 1970'
419+
tm := time.parse_format(dt, format)!
420+
tm_s := tm.custom_format(format)
421+
assert tm_s == 'Th Jan 01 00:00:00 1970'
422+
}
423+
424+
fn test_parse_three_letters_weekday() {
425+
format := 'ddd MMM DD HH:mm:ss YYYY'
426+
dt := 'Sun Jan 01 00:00:00 1970'
427+
tm := time.parse_format(dt, format)!
428+
tm_s := tm.custom_format(format)
429+
assert tm_s == 'Thu Jan 01 00:00:00 1970'
430+
}
431+
432+
fn test_parse_weekday() {
433+
format := 'dddd MMM DD HH:mm:ss YYYY'
434+
dt := 'Sunday Jan 01 00:00:00 1970'
435+
tm := time.parse_format(dt, format)!
436+
tm_s := tm.custom_format(format)
437+
assert tm_s == 'Thursday Jan 01 00:00:00 1970'
438+
}

0 commit comments

Comments
 (0)