-
Notifications
You must be signed in to change notification settings - Fork 1
/
UnixTimes.jl
102 lines (82 loc) · 2.96 KB
/
UnixTimes.jl
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
module UnixTimes
using Dates
using TimeZones
export UnixTime
export unix_now
struct UnixTime <: Dates.AbstractDateTime
instant::Dates.UTInstant{Nanosecond}
end
function UnixTime(
y::Integer,
m::Integer = 1,
d::Integer = 1,
h::Integer = 0,
mi::Integer = 0,
s::Integer = 0,
ms::Integer = 0,
us::Integer = 0,
ns::Integer = 0)
convert(UnixTime, DateTime(y, m, d, h, mi, s, ms)) + Nanosecond(us * 1000 + ns)
end
Dates.days(x::UnixTime) = Dates.days(convert(DateTime, x))
Dates.hour(x::UnixTime) = mod(fld(Dates.value(x), 3600_000_000_000), 24)
Dates.minute(x::UnixTime) = mod(fld(Dates.value(x), 60_000_000_000), 60)
Dates.second(x::UnixTime) = mod(fld(Dates.value(x), 1_000_000_000), 60)
Dates.millisecond(x::UnixTime) = mod(fld(Dates.value(x), 1_000_000), 1000)
Dates.microsecond(x::UnixTime) = mod(fld(Dates.value(x), 1_000), 1000)
Dates.nanosecond(x::UnixTime) = mod(Dates.value(x), 1_000)
Base.:+(x::UnixTime, p::Period) =
UnixTime(Dates.UTInstant(x.instant.periods + Nanosecond(Dates.tons(p))))
Base.:-(x::UnixTime, p::Period) = x + (-p)
function Base.:+(x::UnixTime, p::Union{Month, Year})
trunc_ns = mod(Dates.value(x), 1_000_000)
convert(UnixTime, convert(DateTime, x) + p) + Nanosecond(trunc_ns)
end
function Dates.DateTime(x::UnixTime)
instant_ms = Dates.UNIXEPOCH + div(x.instant.periods.value, 1_000_000)
DateTime(Dates.UTM(instant_ms))
end
Dates.Date(x::UnixTime) = Date(DateTime(x))
Dates.Time(x::UnixTime) = Time(DateTime(x)) # Note: The returned time object has millisecond precision
Base.convert(::Type{DateTime}, x::UnixTime) = DateTime(x)
function UnixTime(x::DateTime)
instant_ns = (Dates.value(x) - Dates.UNIXEPOCH) * 1_000_000
UnixTime(Dates.UTInstant(Nanosecond(instant_ns)))
end
UnixTime(x::Nanosecond) = UnixTime(Dates.UTInstant(x))
UnixTime(x::Date) = UnixTime(DateTime(x))
Base.convert(::Type{UnixTime}, x::DateTime) = UnixTime(x)
UnixTime(x::ZonedDateTime) = UnixTime(DateTime(x, UTC))
ZonedDateTime(x::UnixTime, tz::TimeZone) = ZonedDateTime(DateTime(x), tz; from_utc = true)
function Base.show(io::IO, x::UnixTime)
xdt = convert(DateTime, x)
print(io, Dates.format(xdt, dateformat"yyyy-mm-ddTHH:MM:SS.sss"))
v = x.instant.periods.value
d = 100_000
for i in 1:6
print(io, div(v, d) % 10 + '0')
d = div(d, 10)
end
nothing
end
function Base.floor(x::UnixTime, p::Union{DatePeriod, TimePeriod})
convert(UnixTime, floor(convert(DateTime, x), p))
end
if Sys.islinux()
struct LinuxTimespec
seconds::Clong
nanoseconds::Cuint
end
@inline function unix_now()
ts = Ref{LinuxTimespec}()
ccall(:clock_gettime, Cint, (Cint, Ref{LinuxTimespec}), 0, ts)
x = ts[]
UnixTime(Dates.UTInstant(Nanosecond(x.seconds * 1_000_000_000 + x.nanoseconds)))
end
else
@inline function unix_now()
tv = Libc.TimeVal()
UnixTime(Dates.UTInstant(Nanosecond(tv.sec * 1_000_000_000 + tv.usec * 1_000)))
end
end
end