66# 3. CDF_TIME_TT2000 (TT2000 as short) is nanoseconds since J2000 with leap seconds
77
88import Base: promote_rule, - , +
9+ using Dates: value, toms, tons
910
1011include(" leap_second.jl" )
1112
@@ -14,6 +15,20 @@ const EPOCH_OFFSET_SECONDS = 62167219200.0 # Seconds from year 0 to Unix epoch
1415
1516abstract type CDFDateTime <: Dates.AbstractDateTime end
1617
18+ struct Picosecond <: Period
19+ value:: Float64
20+ end
21+
22+ Picosecond(ns:: Nanosecond ) = convert(Picosecond, ns)
23+ Picosecond(p:: Period ) = Picosecond(Nanosecond(p))
24+ Base. convert(:: Type{Nanosecond} , x:: Picosecond ) = Nanosecond(round(Int64, x. value / 1.0e3 ))
25+ Base. convert(:: Type{Picosecond} , x:: Nanosecond ) = Picosecond(x. value * 1.0e3 )
26+ Base. convert(:: Type{Picosecond} , x:: Dates.FixedPeriod ) = Picosecond(Nanosecond(x))
27+ Base. promote_rule(:: Type{Picosecond} , :: Type{<:Dates.FixedPeriod} ) = Picosecond
28+
29+ Dates. _units(x:: Picosecond ) = " picosecond" * (abs(value(x)) == 1 ? " " : " s" )
30+
31+
1732"""
1833 Epoch
1934
@@ -56,8 +71,11 @@ fillvalue(::Epoch16) = -1.0e31
5671fillvalue(:: TT2000 ) = 9999
5772
5873(- )(epoch:: Epoch , other:: Epoch ) = Millisecond(round(Int64, epoch. instant - other. instant))
59- (+ )(tt2000:: TT2000 , other:: Period ) = TT2000(tt2000. instant. value + Dates. tons(other))
60- (+ )(epoch:: Epoch , other:: Period ) = Epoch(epoch. instant + Dates. toms(other))
74+ (- )(epoch:: Epoch16 , other:: Epoch16 ) = Picosecond((epoch. seconds - other. seconds) * 1.0e12 + epoch. picoseconds - other. picoseconds)
75+ (+ )(tt2000:: TT2000 , other:: Period ) = TT2000(value(tt2000) + tons(other))
76+ (- )(tt2000:: TT2000 , other:: Period ) = TT2000(value(tt2000) - tons(other))
77+ (+ )(epoch:: Epoch , other:: Period ) = Epoch(value(epoch) + toms(other))
78+ (- )(epoch:: Epoch , other:: Period ) = Epoch(value(epoch) - toms(other))
6179
6280# Conversion to DateTime
6381function Dates. DateTime(epoch:: Epoch )
6684
6785function Dates. DateTime(epoch:: Epoch16 )
6886 s_since_unix = epoch. seconds - EPOCH_OFFSET_SECONDS
69- total_ns = s_since_unix * 1.0e9 + epoch. picoseconds / 1000.0
70- return DateTime(1970 ) + Nanosecond (round(Int64, total_ns ))
87+ total_ms = s_since_unix * 1.0e3 + epoch. picoseconds / 1.0e9
88+ return DateTime(1970 ) + Millisecond (round(Int64, total_ms ))
7189end
7290
7391function Dates. DateTime(epoch:: TT2000 )
7997
8098# Conversion from TimeType
8199function Epoch16(dt:: DateTime )
82- ns_since_unix = (dt - DateTime(1970 , 1 , 1 )). value * 1_000_000 # DateTime precision is milliseconds
83- s_since_unix = ns_since_unix / 1.0e9
100+ ms_since_unix = value (dt - DateTime(1970 , 1 , 1 ))
101+ s_since_unix = div(ms_since_unix, 1000 )
84102 s_total = s_since_unix + EPOCH_OFFSET_SECONDS
85- ps_component = (ns_since_unix % 1.0e9 ) * 1000.0 # Convert nanoseconds remainder to picoseconds
103+ ps_component = rem(ms_since_unix, 1000 ) * 1000000000 # Convert nanoseconds remainder to picoseconds
86104 return Epoch16(s_total, ps_component)
87105end
88106
@@ -102,11 +120,12 @@ for f in (:year, :month, :day, :hour, :minute, :second, :millisecond)
102120 @eval Dates.$ f(epoch:: CDFDateTime ) = Dates.$ f(DateTime(epoch))
103121end
104122
105- Dates. value(epoch:: CDFDateTime ) = epoch. instant
123+ Dates. value(epoch:: Epoch ) = epoch. instant
124+ Dates. value(epoch:: Epoch16 ) = ComplexF64(epoch. seconds, epoch. picoseconds)
106125Dates. value(epoch:: TT2000 ) = epoch. instant. value
107126
108127function Base. floor(x:: T , p:: Union{DatePeriod, TimePeriod} ) where {T <: CDFDateTime }
109- convert(T, floor(convert(DateTime, x), p))
128+ return convert(T, floor(convert(DateTime, x), p))
110129end
111130
112131function Base. show(io:: IO , epoch:: CDFDateTime )
@@ -117,7 +136,12 @@ function Base.show(io::IO, epoch::CDFDateTime)
117136 print(io, DateTime(epoch))
118137 end
119138end
139+ function Base. show(io:: IO , epoch:: Epoch16 )
140+ return print(io, DateTime(epoch))
141+ end
142+
120143Base. promote_rule(:: Type{<:CDFDateTime} , :: Type{Dates.DateTime} ) = Dates. DateTime
121144Base. convert(:: Type{Dates.DateTime} , x:: CDFDateTime ) = Dates. DateTime(x)
122- Base. bswap(x:: T ) where {T <: CDFDateTime } = T(Base. bswap(x. instant))
145+ Base. bswap(x:: Epoch ) = Epoch(Base. bswap(x. instant))
146+ Base. bswap(x:: Epoch16 ) = Epoch16(Base. bswap(x. seconds), Base. bswap(x. picoseconds))
123147Base. bswap(x:: TT2000 ) = TT2000(Base. bswap(x. instant. value))
0 commit comments