Skip to content

Commit c1db600

Browse files
authored
time: fix more panics in the supported specifiers in Time.custom_format/1 (#24988)
1 parent 6aede65 commit c1db600

3 files changed

Lines changed: 26 additions & 20 deletions

File tree

‎vlib/time/custom_format_test.v‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,9 @@ fn test_hours() {
3636
assert time.parse('2023-08-04 22:00:45')!.custom_format('ii A i a hh A h a') == '10 PM 10 pm 10 PM 10 pm'
3737
assert time.parse('2023-08-04 23:00:45')!.custom_format('ii A i a hh A h a') == '11 PM 11 pm 11 PM 11 pm'
3838
}
39+
40+
fn test_zero_date() {
41+
zero_date := time.Time{}
42+
res := zero_date.custom_format('M MM Mo MMM MMMM |1| D DD DDD DDDD |2| d dd ddd dddd |3| YY YYYY a A |4| H HH h hh k kk i ii e |5| m mm s ss |6| Do DDDo Q Qo QQ |7| N NN |8| M/D/YYYY N-HH:mm:ss Qo?a')
43+
assert res == '0 00 0th Jan January |1| 0 00 0 000 |2| -1 Mo Mon Monday |3| 0 am AM |4| 0 00 12 12 1 01 0 00 e |5| 0 00 0 00 |6| 0th 0th 1 1st 01 |7| AD Anno Domini |8| 0/0/0 AD-00:00:00 1st?am'
44+
}

‎vlib/time/format.v‎

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ module time
55

66
import strings
77

8+
fn iclamp(x int, a int, b int) int {
9+
if x < a {
10+
return a
11+
}
12+
if x > b {
13+
return b
14+
}
15+
return x
16+
}
17+
818
// int_to_byte_array_no_pad fulfill buffer by part
919
// it doesn't pad with leading zeros for performance reasons
1020
@[direct_array_access]
@@ -401,20 +411,10 @@ pub fn (t Time) custom_format(s string) string {
401411
sb.write_string(ordinal_suffix(t.month))
402412
}
403413
'MMM' {
404-
m := if t.month >= 1 && t.month <= 12 {
405-
long_months[t.month - 1][0..3]
406-
} else {
407-
long_months[0][0..3]
408-
}
409-
sb.write_string(m)
414+
sb.write_string(long_months[iclamp(0, t.month - 1, 11)][0..3])
410415
}
411416
'MMMM' {
412-
m := if t.month >= 1 && t.month <= 12 {
413-
long_months[t.month - 1]
414-
} else {
415-
long_months[0]
416-
}
417-
sb.write_string(m)
417+
sb.write_string(long_months[iclamp(0, t.month - 1, 11)])
418418
}
419419
'D' {
420420
sb.write_string(t.day.str())
@@ -438,16 +438,16 @@ pub fn (t Time) custom_format(s string) string {
438438
sb.write_string('${t.day_of_week() % 7}')
439439
}
440440
'dd' {
441-
sb.write_string(long_days[t.day_of_week() - 1][0..2])
441+
sb.write_string(long_days[iclamp(0, t.day_of_week() - 1, 6)][0..2])
442442
}
443443
'ddd' {
444-
sb.write_string(long_days[t.day_of_week() - 1][0..3])
444+
sb.write_string(long_days[iclamp(0, t.day_of_week() - 1, 6)][0..3])
445445
}
446446
'dddd' {
447-
sb.write_string(long_days[t.day_of_week() - 1])
447+
sb.write_string(long_days[iclamp(0, t.day_of_week() - 1, 6)])
448448
}
449449
'YY' {
450-
sb.write_string(t.year.str()[2..4])
450+
sb.write_string(t.year.str()#[2..4])
451451
}
452452
'YYYY' {
453453
sb.write_string(t.year.str())

‎vlib/time/time.v‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ pub fn day_of_week(y int, m int, d int) int {
288288
if m < 3 {
289289
sy = sy - 1
290290
}
291-
return (sy + sy / 4 - sy / 100 + sy / 400 + t[m - 1] + d - 1) % 7 + 1
291+
return (sy + sy / 4 - sy / 100 + sy / 400 + t[iclamp(0, m - 1, 11)] + d - 1) % 7 + 1
292292
}
293293

294294
// day_of_week returns the current day as an integer.
@@ -330,7 +330,7 @@ pub fn (t Time) week_of_year() int {
330330
// year_day returns the current day of the year as an integer.
331331
// See also #Time.custom_format .
332332
pub fn (t Time) year_day() int {
333-
yday := t.day + days_before[t.month - 1]
333+
yday := t.day + days_before[iclamp(0, t.month - 1, 12)]
334334
if is_leap_year(t.year) && t.month > 2 {
335335
return yday + 1
336336
}
@@ -340,13 +340,13 @@ pub fn (t Time) year_day() int {
340340
// weekday_str returns the current day as a string 3 letter abbreviation.
341341
pub fn (t Time) weekday_str() string {
342342
i := t.day_of_week() - 1
343-
return long_days[i][0..3]
343+
return long_days[iclamp(0, i, 6)][0..3]
344344
}
345345

346346
// long_weekday_str returns the current day as a string.
347347
pub fn (t Time) long_weekday_str() string {
348348
i := t.day_of_week() - 1
349-
return long_days[i]
349+
return long_days[iclamp(0, i, 6)]
350350
}
351351

352352
// is_leap_year checks if a given a year is a leap year.

0 commit comments

Comments
 (0)