mirror of
https://github.com/vlang/v.git
synced 2025-09-09 23:39:39 -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))
|
sb.write_string(ordinal_suffix(t.day))
|
||||||
}
|
}
|
||||||
'DDD' {
|
'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' {
|
'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' {
|
'DDDo' {
|
||||||
sb.write_string(ordinal_suffix(t.day + days_before[t.month - 1] +
|
sb.write_string(ordinal_suffix(t.year_day()))
|
||||||
int(is_leap_year(t.year))))
|
|
||||||
}
|
}
|
||||||
'd' {
|
'd' {
|
||||||
sb.write_string('${t.day_of_week() % 7}')
|
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}')
|
sb.write_string('${(t.hour + 1):02}')
|
||||||
}
|
}
|
||||||
'w' {
|
'w' {
|
||||||
sb.write_string('${mceil((t.day + days_before[t.month - 1] +
|
sb.write_string('${t.week_of_year():.0}')
|
||||||
int(is_leap_year(t.year))) / 7):.0}')
|
|
||||||
}
|
}
|
||||||
'ww' {
|
'ww' {
|
||||||
sb.write_string('${mceil((t.day + days_before[t.month - 1] +
|
sb.write_string('${t.week_of_year():02.0}')
|
||||||
int(is_leap_year(t.year))) / 7):02.0}')
|
|
||||||
}
|
}
|
||||||
'wo' {
|
'wo' {
|
||||||
sb.write_string(ordinal_suffix(int(mceil((t.day + days_before[t.month - 1] +
|
sb.write_string(ordinal_suffix(t.week_of_year()))
|
||||||
int(is_leap_year(t.year))) / 7))))
|
|
||||||
}
|
}
|
||||||
'Q' {
|
'Q' {
|
||||||
sb.write_string('${(t.month % 4) + 1}')
|
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)
|
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.
|
// year_day returns the current day of the year as an integer.
|
||||||
// See also #Time.custom_format .
|
// See also #Time.custom_format .
|
||||||
pub fn (t Time) year_day() int {
|
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() {
|
fn test_year_day() {
|
||||||
// testing if December 31st in a leap year is numbered as 366
|
// testing if December 31st in a leap year is numbered as 366
|
||||||
assert time.parse('2024-12-31 20:00:00')!.year_day() == 366
|
assert time.parse('2024-12-31 20:00:00')!.year_day() == 366
|
||||||
|
Loading…
x
Reference in New Issue
Block a user