mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
time: rewrite unix() function
This commit is contained in:

committed by
Alexander Medvednikov

parent
67912c692b
commit
286a0a1371
113
vlib/time/time_unix.v
Normal file
113
vlib/time/time_unix.v
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
module time
|
||||
|
||||
pub fn unix(abs int) Time {
|
||||
// Split into day and time
|
||||
mut day_offset := abs / seconds_per_day
|
||||
if abs % seconds_per_day < 0 {
|
||||
// Compensate for round towards zero on integers as we want floored instead
|
||||
day_offset -= 1
|
||||
}
|
||||
year, month, day := calculate_date_from_offset(day_offset)
|
||||
hr, min, sec := calculate_time_from_offset(abs % seconds_per_day)
|
||||
return Time{
|
||||
year: year
|
||||
month: month
|
||||
day: day
|
||||
hour: hr
|
||||
minute: min
|
||||
second: sec
|
||||
unix: abs
|
||||
}
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn calculate_date_from_offset(day_offset_ int) (int, int, int) {
|
||||
mut day_offset := day_offset_
|
||||
|
||||
// Move offset to year 2001 as it's the start of a new 400-year cycle
|
||||
// Code below this rely on the fact that the day_offset is lined up with the 400-year cycle
|
||||
// 1970-2000 (inclusive) has 31 years (8 of which are leap years)
|
||||
mut year := 2001
|
||||
day_offset -= 31*365 + 8
|
||||
|
||||
// Account for 400 year cycle
|
||||
year += (day_offset / days_per_400_years) * 400
|
||||
day_offset %= days_per_400_years
|
||||
|
||||
// Account for 100 year cycle
|
||||
if day_offset == days_per_100_years * 4 {
|
||||
year += 300
|
||||
day_offset -= days_per_100_years * 3
|
||||
} else {
|
||||
year += (day_offset / days_per_100_years) * 100
|
||||
day_offset %= days_per_100_years
|
||||
}
|
||||
|
||||
// Account for 4 year cycle
|
||||
if day_offset == days_per_4_years * 25 {
|
||||
year += 96
|
||||
day_offset -= days_per_4_years * 24
|
||||
} else {
|
||||
year += (day_offset / days_per_4_years) * 4
|
||||
day_offset %= days_per_4_years
|
||||
}
|
||||
|
||||
// Account for every year
|
||||
if day_offset == 365 * 4 {
|
||||
year += 3
|
||||
day_offset -= 365 * 3
|
||||
} else {
|
||||
year += (day_offset / 365)
|
||||
day_offset %= 365
|
||||
}
|
||||
|
||||
if day_offset < 0 {
|
||||
year -= 1
|
||||
if is_leap_year(year) {
|
||||
day_offset += 366
|
||||
} else {
|
||||
day_offset += 365
|
||||
}
|
||||
}
|
||||
|
||||
if is_leap_year(year) {
|
||||
if day_offset > 31 + 29 - 1 {
|
||||
// After leap day; pretend it wasn't there.
|
||||
day_offset--
|
||||
} else if day_offset == 31 + 29 - 1 {
|
||||
// Leap day.
|
||||
return year, 2, 29
|
||||
}
|
||||
}
|
||||
|
||||
mut estimated_month := day_offset / 31
|
||||
for day_offset > days_before[estimated_month+1] {
|
||||
estimated_month++
|
||||
}
|
||||
for day_offset <= days_before[estimated_month] {
|
||||
estimated_month--
|
||||
}
|
||||
|
||||
day_offset -= days_before[estimated_month]
|
||||
|
||||
return year, estimated_month+1, day_offset+1
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn calculate_time_from_offset(second_offset_ int) (int, int, int) {
|
||||
mut second_offset := second_offset_
|
||||
if second_offset < 0 {
|
||||
second_offset += seconds_per_day
|
||||
}
|
||||
|
||||
hour := second_offset / seconds_per_hour
|
||||
second_offset %= seconds_per_hour
|
||||
|
||||
min := second_offset / seconds_per_minute
|
||||
second_offset %= seconds_per_minute
|
||||
|
||||
return hour, min, second_offset
|
||||
}
|
Reference in New Issue
Block a user