time: fix more panics in the supported specifiers in Time.custom_format/1 (#24988)

This commit is contained in:
Delyan Angelov 2025-07-27 20:34:11 +03:00 committed by GitHub
parent 6aede65485
commit c1db6006bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 20 deletions

View File

@ -36,3 +36,9 @@ fn test_hours() {
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'
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'
}
fn test_zero_date() {
zero_date := time.Time{}
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')
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'
}

View File

@ -5,6 +5,16 @@ module time
import strings
fn iclamp(x int, a int, b int) int {
if x < a {
return a
}
if x > b {
return b
}
return x
}
// int_to_byte_array_no_pad fulfill buffer by part
// it doesn't pad with leading zeros for performance reasons
@[direct_array_access]
@ -401,20 +411,10 @@ pub fn (t Time) custom_format(s string) string {
sb.write_string(ordinal_suffix(t.month))
}
'MMM' {
m := if t.month >= 1 && t.month <= 12 {
long_months[t.month - 1][0..3]
} else {
long_months[0][0..3]
}
sb.write_string(m)
sb.write_string(long_months[iclamp(0, t.month - 1, 11)][0..3])
}
'MMMM' {
m := if t.month >= 1 && t.month <= 12 {
long_months[t.month - 1]
} else {
long_months[0]
}
sb.write_string(m)
sb.write_string(long_months[iclamp(0, t.month - 1, 11)])
}
'D' {
sb.write_string(t.day.str())
@ -438,16 +438,16 @@ pub fn (t Time) custom_format(s string) string {
sb.write_string('${t.day_of_week() % 7}')
}
'dd' {
sb.write_string(long_days[t.day_of_week() - 1][0..2])
sb.write_string(long_days[iclamp(0, t.day_of_week() - 1, 6)][0..2])
}
'ddd' {
sb.write_string(long_days[t.day_of_week() - 1][0..3])
sb.write_string(long_days[iclamp(0, t.day_of_week() - 1, 6)][0..3])
}
'dddd' {
sb.write_string(long_days[t.day_of_week() - 1])
sb.write_string(long_days[iclamp(0, t.day_of_week() - 1, 6)])
}
'YY' {
sb.write_string(t.year.str()[2..4])
sb.write_string(t.year.str()#[2..4])
}
'YYYY' {
sb.write_string(t.year.str())

View File

@ -288,7 +288,7 @@ pub fn day_of_week(y int, m int, d int) int {
if m < 3 {
sy = sy - 1
}
return (sy + sy / 4 - sy / 100 + sy / 400 + t[m - 1] + d - 1) % 7 + 1
return (sy + sy / 4 - sy / 100 + sy / 400 + t[iclamp(0, m - 1, 11)] + d - 1) % 7 + 1
}
// day_of_week returns the current day as an integer.
@ -330,7 +330,7 @@ pub fn (t Time) week_of_year() int {
// year_day returns the current day of the year as an integer.
// See also #Time.custom_format .
pub fn (t Time) year_day() int {
yday := t.day + days_before[t.month - 1]
yday := t.day + days_before[iclamp(0, t.month - 1, 12)]
if is_leap_year(t.year) && t.month > 2 {
return yday + 1
}
@ -340,13 +340,13 @@ pub fn (t Time) year_day() int {
// weekday_str returns the current day as a string 3 letter abbreviation.
pub fn (t Time) weekday_str() string {
i := t.day_of_week() - 1
return long_days[i][0..3]
return long_days[iclamp(0, i, 6)][0..3]
}
// long_weekday_str returns the current day as a string.
pub fn (t Time) long_weekday_str() string {
i := t.day_of_week() - 1
return long_days[i]
return long_days[iclamp(0, i, 6)]
}
// is_leap_year checks if a given a year is a leap year.