mirror of
https://github.com/vlang/v.git
synced 2025-09-08 14:51:53 -04:00
time: add .week_of_year() method for time.Time instances (#23838)
This commit is contained in:
parent
05a6e557cf
commit
57a45bc353
@ -416,14 +416,13 @@ pub fn (t Time) custom_format(s string) string {
|
||||
sb.write_string(ordinal_suffix(t.day))
|
||||
}
|
||||
'DDD' {
|
||||
sb.write_string((t.day + days_before[t.month - 1] + int(is_leap_year(t.year))).str())
|
||||
sb.write_string((t.year_day()).str())
|
||||
}
|
||||
'DDDD' {
|
||||
sb.write_string('${t.day + days_before[t.month - 1] + int(is_leap_year(t.year)):03}')
|
||||
sb.write_string('${t.year_day():03}')
|
||||
}
|
||||
'DDDo' {
|
||||
sb.write_string(ordinal_suffix(t.day + days_before[t.month - 1] +
|
||||
int(is_leap_year(t.year))))
|
||||
sb.write_string(ordinal_suffix(t.year_day()))
|
||||
}
|
||||
'd' {
|
||||
sb.write_string('${t.day_of_week() % 7}')
|
||||
@ -484,16 +483,13 @@ pub fn (t Time) custom_format(s string) string {
|
||||
sb.write_string('${(t.hour + 1):02}')
|
||||
}
|
||||
'w' {
|
||||
sb.write_string('${mceil((t.day + days_before[t.month - 1] +
|
||||
int(is_leap_year(t.year))) / 7):.0}')
|
||||
sb.write_string('${t.week_of_year():.0}')
|
||||
}
|
||||
'ww' {
|
||||
sb.write_string('${mceil((t.day + days_before[t.month - 1] +
|
||||
int(is_leap_year(t.year))) / 7):02.0}')
|
||||
sb.write_string('${t.week_of_year():02.0}')
|
||||
}
|
||||
'wo' {
|
||||
sb.write_string(ordinal_suffix(int(mceil((t.day + days_before[t.month - 1] +
|
||||
int(is_leap_year(t.year))) / 7))))
|
||||
sb.write_string(ordinal_suffix(t.week_of_year()))
|
||||
}
|
||||
'Q' {
|
||||
sb.write_string('${(t.month % 4) + 1}')
|
||||
|
@ -296,6 +296,37 @@ pub fn (t Time) day_of_week() int {
|
||||
return day_of_week(t.year, t.month, t.day)
|
||||
}
|
||||
|
||||
// week_of_year returns the current week of year as an integer.
|
||||
// follow ISO 8601 standard
|
||||
pub fn (t Time) week_of_year() int {
|
||||
// ISO 8601 Week of Year Rules:
|
||||
// --------------------------------------------
|
||||
// 1. Week Definition:
|
||||
// - A week starts on **Monday** (Day 1) and ends on **Sunday** (Day 7).
|
||||
// 2. First Week of the Year:
|
||||
// - The first week is the one containing the year's **first Thursday**.
|
||||
// - Equivalently, the week with January 4th always belongs to Week 1.
|
||||
// 3. Year Assignment:
|
||||
// - Dates in December/January may belong to the previous/next ISO year,
|
||||
// depending on the week's Thursday.
|
||||
// 4. Week Number Format:
|
||||
// - Expressed as `YYYY-Www` (e.g., `2026-W01` for the first week of 2026).
|
||||
// --------------------------------------------
|
||||
// Algorithm Steps:
|
||||
// 1. Find the Thursday of the current week:
|
||||
// - If date is Monday-Wednesday, add days to reach Thursday.
|
||||
// - If date is Thursday-Sunday, subtract days to reach Thursday.
|
||||
// 2. The ISO year is the calendar year of this Thursday.
|
||||
// 3. Compute the week number as:
|
||||
// week_number = (thursday's day_of_year - 1) / 7 + 1
|
||||
day_of_week := t.day_of_week()
|
||||
days_to_thursday := 4 - day_of_week
|
||||
thursday_date := t.add_days(days_to_thursday)
|
||||
thursday_day_of_year := thursday_date.year_day()
|
||||
week_number := (thursday_day_of_year - 1) / 7 + 1
|
||||
return week_number
|
||||
}
|
||||
|
||||
// year_day returns the current day of the year as an integer.
|
||||
// See also #Time.custom_format .
|
||||
pub fn (t Time) year_day() int {
|
||||
|
@ -201,6 +201,34 @@ fn test_day_of_week() {
|
||||
}
|
||||
}
|
||||
|
||||
fn test_week_of_year() {
|
||||
// As windows use msvcrt.dll, which `strftime` does not support %V, so skip test
|
||||
// TODO: newer version windows use ucrtbase.dll, which support %V
|
||||
$if !windows {
|
||||
for year in 2000 .. 2100 {
|
||||
mut t := time.new(time.Time{
|
||||
year: year
|
||||
month: 12
|
||||
day: 20
|
||||
})
|
||||
|
||||
// check from year.12.20 to next_year.1.8
|
||||
for _ in 0 .. 20 {
|
||||
assert t.strftime('%V') == '${t.week_of_year():02}', '${t}'
|
||||
t = t.add_days(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t1 := time.Time{
|
||||
year: 2025
|
||||
month: 3
|
||||
day: 3
|
||||
}
|
||||
assert t1.week_of_year() == 10
|
||||
assert t1.add_days(1).week_of_year() == 10
|
||||
}
|
||||
|
||||
fn test_year_day() {
|
||||
// testing if December 31st in a leap year is numbered as 366
|
||||
assert time.parse('2024-12-31 20:00:00')!.year_day() == 366
|
||||
|
Loading…
x
Reference in New Issue
Block a user