aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/old/vlib/time/unix.v
blob: ac9d0100b601a2f950f919ebdf9a0a1823add555 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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 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
		unix: u64(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: u64(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)
}