1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00
v/vlib/time/unix.v

127 lines
3.3 KiB
V
Raw Normal View History

2020-01-23 23:04:46 +03:00
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
2019-12-31 19:11:47 +03:00
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module time
2020-02-06 16:19:44 +03:00
// unix returns a time struct from Unix time.
2019-12-31 19:11:47 +03:00
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
2020-01-23 23:09:47 +03:00
day_offset--
2019-12-31 19:11:47 +03:00
}
2020-12-06 17:19:39 +03:00
year, month, day := calculate_date_from_offset(day_offset)
hr, min, sec := calculate_time_from_offset(abs % seconds_per_day)
2019-12-31 19:11:47 +03:00
return Time{
year: year
month: month
day: day
hour: hr
minute: min
second: sec
unix: u64(abs)
2019-12-31 19:11:47 +03:00
}
}
// unix2 returns a time struct from Unix time and microsecond value
pub fn unix2(abs int, microsecond 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--
}
2020-12-06 17:19:39 +03:00
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
microsecond: microsecond
unix: u64(abs)
}
}
2019-12-31 19:11:47 +03:00
[inline]
2020-12-06 17:19:39 +03:00
fn calculate_date_from_offset(day_offset_ int) (int, int, int) {
2019-12-31 19:11:47 +03:00
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
2020-01-23 23:09:47 +03:00
day_offset -= 31 * 365 + 8
2019-12-31 19:11:47 +03:00
// 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
2020-12-06 17:19:39 +03:00
} else {
2019-12-31 19:11:47 +03:00
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
2020-12-06 17:19:39 +03:00
} else {
2019-12-31 19:11:47 +03:00
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
2020-12-06 17:19:39 +03:00
} else {
2019-12-31 19:11:47 +03:00
year += (day_offset / 365)
day_offset %= 365
}
if day_offset < 0 {
2020-01-23 23:09:47 +03:00
year--
2019-12-31 19:11:47 +03:00
if is_leap_year(year) {
day_offset += 366
2020-12-06 17:19:39 +03:00
} else {
2019-12-31 19:11:47 +03:00
day_offset += 365
}
}
if is_leap_year(year) {
if day_offset > 31 + 29 - 1 {
// After leap day; pretend it wasn't there.
day_offset--
2020-12-06 17:19:39 +03:00
} else if day_offset == 31 + 29 - 1 {
2019-12-31 19:11:47 +03:00
// Leap day.
2020-12-06 17:19:39 +03:00
return year, 2, 29
2019-12-31 19:11:47 +03:00
}
}
mut estimated_month := day_offset / 31
2020-01-23 23:09:47 +03:00
for day_offset >= days_before[estimated_month + 1] {
2019-12-31 19:11:47 +03:00
estimated_month++
}
2020-01-14 20:12:28 +03:00
for day_offset < days_before[estimated_month] {
if estimated_month == 0 {
break
}
2019-12-31 19:11:47 +03:00
estimated_month--
}
day_offset -= days_before[estimated_month]
2020-12-06 17:19:39 +03:00
return year, estimated_month + 1, day_offset + 1
2019-12-31 19:11:47 +03:00
}
[inline]
2020-12-06 17:19:39 +03:00
fn calculate_time_from_offset(second_offset_ int) (int, int, int) {
2019-12-31 19:11:47 +03:00
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
2020-12-06 17:19:39 +03:00
return hour, min, second_offset
2019-12-31 19:11:47 +03:00
}