aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/vlib/time/unix.v
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/vlib/time/unix.v')
-rw-r--r--v_windows/v/vlib/time/unix.v124
1 files changed, 124 insertions, 0 deletions
diff --git a/v_windows/v/vlib/time/unix.v b/v_windows/v/vlib/time/unix.v
new file mode 100644
index 0000000..30cae42
--- /dev/null
+++ b/v_windows/v/vlib/time/unix.v
@@ -0,0 +1,124 @@
+// Copyright (c) 2019-2021 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
+
+// unix returns a time struct from Unix time.
+pub fn unix(abs i64) 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--
+ }
+ 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
+ }
+}
+
+// unix2 returns a time struct from Unix time and microsecond value
+pub fn unix2(abs i64, 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--
+ }
+ 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: abs
+ }
+}
+
+fn calculate_date_from_offset(day_offset_ i64) (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 += int(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 += int(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 += int(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 += int(day_offset / 365)
+ day_offset %= 365
+ }
+ if day_offset < 0 {
+ year--
+ 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] {
+ if estimated_month == 0 {
+ break
+ }
+ estimated_month--
+ }
+ day_offset -= days_before[estimated_month]
+ return year, int(estimated_month + 1), int(day_offset + 1)
+}
+
+fn calculate_time_from_offset(second_offset_ i64) (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 int(hour_), int(min), int(second_offset)
+}