1// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module time
5
6#include <time.h>
7
8struct C.tm {
9	tm_sec  int
10	tm_min  int
11	tm_hour int
12	tm_mday int
13	tm_mon  int
14	tm_year int
15	tm_wday int
16	tm_yday int
17	tm_isdst int
18}
19
20fn C.timegm(&tm) time_t
21fn C.localtime_r(t &C.time_t, tm &C.tm )
22
23fn make_unix_time(t C.tm) int {
24	return int(C.timegm(&t))
25}
26
27fn to_local_time(t Time) Time {
28	loc_tm := C.tm{}
29	C.localtime_r(time_t(&t.unix), &loc_tm)
30
31	return convert_ctime(loc_tm, t.microsecond)
32}
33
34type time_t voidptr
35
36// in most systems, these are __quad_t, which is an i64
37struct C.timespec {
38mut:
39	tv_sec  i64
40	tv_nsec i64
41}
42
43// the first arg is defined in include/bits/types.h as `__S32_TYPE`, which is `int`
44fn C.clock_gettime(int, &C.timespec)
45
46pub fn sys_mono_now() u64 {
47	$if macos {
48		return sys_mono_now_darwin()
49	} $else {
50		ts := C.timespec{}
51		C.clock_gettime(C.CLOCK_MONOTONIC, &ts)
52		return u64(ts.tv_sec) * 1_000_000_000 + u64(ts.tv_nsec)
53	}
54}
55
56// NB: vpc_now is used by `v -profile` .
57// It should NOT call *any other v function*, just C functions and casts.
58[inline]
59fn vpc_now() u64 {
60	ts := C.timespec{}
61	C.clock_gettime(C.CLOCK_MONOTONIC, &ts)
62	return u64(ts.tv_sec) * 1_000_000_000 + u64(ts.tv_nsec)
63}
64
65
66
67// dummy to compile with all compilers
68pub fn win_now() Time {
69	return Time{}
70}
71
72// dummy to compile with all compilers
73pub fn win_utc() Time {
74	return Time{}
75}
76
77// dummy to compile with all compilers
78pub struct C.timeval {
79	tv_sec  u64
80	tv_usec u64
81}
82
83// return absolute timespec for now()+d
84pub fn (d Duration) timespec() C.timespec {
85	mut ts := C.timespec{}
86	C.clock_gettime(C.CLOCK_REALTIME, &ts)
87	d_sec := d / second
88	d_nsec := d % second
89	ts.tv_sec += d_sec
90	ts.tv_nsec += d_nsec
91	if ts.tv_nsec > second {
92		ts.tv_nsec -= second
93		ts.tv_sec++
94	}
95	return ts
96}
97
98// return timespec of 1970/1/1
99pub fn zero_timespec() C.timespec {
100	ts := C.timespec{
101		tv_sec:  0
102		tv_nsec: 0
103	}
104	return ts
105}
106