I need a faster implementation of FractionOfYear
and FractionOfMonth
, which do the following:
Input: A time/date specified by {y_, m_, d_, h_, n_, s_}
Output: A real number from 0 to 1 representing the fraction of the year or month that the given time/date spec occurs in.
Leap days and leap seconds complicate things, so I thought I could just rely on DateDifference
, but it is too slow:
RandomDateList[] := {RandomInteger[{1800, 2100}], RandomInteger[{1, 12}], RandomInteger[{1, 28}], RandomInteger[{0, 23}], RandomInteger[{0, 59}], RandomInteger[{0, 59}]};
RandomDates[n_] := Table[RandomDateList[],{n}]
secondOfYear[{y_, m_, d_, h_, n_, s_}] :=
First[DateDifference[{y - 1, 12, 31, 24, 0, 0}, {y, m, d, h, n, s},
"Second"]] / First[DateDifference[{y - 1, 12, 31, 24, 0, 0}, {y, 12, 31, 24, 0, 0}, "Second"]]
secondOfMonth[{y_, m_, d_, h_, n_, s_}] := First[DateDifference[{y, m, 1, 0, 0, 0},
{y, m, d, h, n, s}, "Second"]]/First[DateDifference[{y, m, 1, 0, 0, 0}, If[m==12, {y+1, 1, 1, 0, 0, 0}, {y, m+1, 1, 0, 0, 0}], "Second"]]
AbsoluteTiming [secondOfYear /@ RandomDates[1000]]
takes 6 seconds.
There must be a faster easier way of doing this! I'll accept the first answer that takes under a second for 100,000 elements.
AbsoluteTime
is compilable, and when youMap
it onto a large list of dates, it is still very fast (Map
auto-compiles). Java solution is only about 1.5 times faster, and first few times perhaps even slower (due the Java HotSpot JIT warm-up most likely). I can post it for didactic purposes, but I'd go withAbsoluteTime
. $\endgroup$