Is there an easy way to convert date/datetime to a float representing year? I.e. f(2000-01-01) = 2000, f(2015-07-01) ~ 2015.5 and so on. The most obvious method is 2000 + (x - DateTime(2000, 1, 1)) / (DateTime(2001, 1, 1) - DateTime(2000, 1, 1))
, but it is only approximate, of course, and becomes more and more wrong for dates far from the reference point (2000 in this case).
I sometimes (in PyPlot surface plots) use this:
(y,m,d) = (Dates.year.(dN),Dates.month.(dN),Dates.day.(dN))
DaysInMonth = Dates.daysinmonth.(dN)
RelDayInMonth = (d.-1)./DaysInMonth
utDatum = y + (m.-1)/12 + RelDayInMonth*1/12
const DTM = Union{Date, DateTime}
# assuming you want 2000-01-01 to become 2000.0
yfrac(dtm::DTM) = (dayofyear(dtm) - 1) / daysinyear(dtm)
decimaldate(dtm::DTM) = year(dtm) + yfrac(dtm)
CAUTION: decimaldate
is inexact.
Thanks, this looks like exactly what I need! What do you mean by inexact?
Using floating point values rather than rational values to represent a wide swath of highly resolved times is inherently inexact.
You are representing a real number using a binary floating point representation
Binary floating point representation cannot even represent 0.1 (aka 1/10) exactly!!!
julia> 0.1 + 0.1 + 0.1
0.30000000000000004
"using Precision Decimal Floating Point module (not avail to public)"
julia> using PDFPs
julia> PDFP_setDefaultPrecision(4)
4
julia> PDFP("0.1") + PDFP("0.1") + PDFP("0.1")
PDFP(0, -1, [3, 0, 0, 0])
julia> PDFP_toCommonString(ans)
"0.3000"
julia> PDFP_toExplainationString( PDFP("0.1") + PDFP("0.1") + PDFP("0.1") )
"+1 * 3.000 * 10^-1"
Sure, but it is inherent to all float values, and not related to conversion from date.
In case anyone encounters this thread looking for a solution.
I published a package Alexander Plavin / DateFormats.jl · GitLab (registered in General) earlier this year. It converts Dates and DateTimes to/from a range of formats, including decimal year (e.g. 2021.45). The implemented conversion is more accurate than the one posted above.