Last active
March 31, 2017 03:20
-
-
Save JeffreySarnoff/4191491 to your computer and use it in GitHub Desktop.
still daynumbers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#= | |
# | |
# filename: DayNumber.jl | |
# | |
# part of : Time for Julia | |
# in part : my own software | |
# | |
# purpose : canonical daycounts for TAI dates | |
# | |
# offers : ymd_to_daynumber, daynumber_to_ymd | |
# | |
# caution : IT IS AN UNCHECKED ERROR | |
# to use a year not in [ -4399 .. +4399 ] | |
# to use daynumber not in [ +366 .. +3214133 ] | |
# | |
# language: Julia (written for ver 0.0.0 >= 2012-11-29) | |
# (updated for ver 0.5+ >= 2016-Jun-01) | |
# | |
# author : Jeffrey A. Sarnoff | |
# | |
# created : 2012-Jul-02 10:20 America/New_York | |
# edited : 2012-Dec-02 17:40 America/New_York | |
# updated : 2017-Mar-08 19:31 America/New_York | |
# | |
# rights : This work is available for use with Julia without restriction. | |
# | |
=# | |
module DayNumber | |
export | |
ymd_to_daynumber, daynumber_to_ymd | |
# Dates in a proleptic Gregorian calendar using year zero. | |
# | |
# daynumber_to_ymd( ymd_to_daynumber(y,m,d) ) == y,m,d | |
# | |
# exhaustively verified for all accepted dates | |
# in the years: [ -3999.. -1, 0, +1 ..3999 ] | |
# convert date into a nonnegative daynumber | |
# dates change at midnight (a fact not used in this function) | |
# months: Jan=1,..,Dec=12, days: 1..31 | |
# supports years (-3999..,-2,-1,0,1,2,..3999) | |
# aligns with the Gregorian 400 year cycle (146907 days) | |
# multiples of 400 years have daynumber multiples of 146097 | |
# this is true for positive and for negative years | |
# requires year numbered using the non-historical Year 0 | |
# uses a non-historical proleptic Gregorian calendar | |
# historically, year 8 is the first year properly a leap year | |
# | |
# Notes | |
# to obtain the corresponding Int64 daynumber subtract 1607067 | |
# | |
# ( y, m, d) --> daynumber, description | |
# | |
# ( 4400, 1, 1) --> 3214134 [ and that is the soft clopen upper bound] | |
# ( 4399,12,31) --> 3214133 [ and that is the soft realized upper bound] | |
# | |
# ( 3999,12,31) --> 3068036 [ exhaustively verified upper bound ] | |
# | |
# ( 1970, 1, 1) --> 2326595 [ UNIX Epoch (zero) ] | |
# ( 1, 1, 1) --> 1607433 | |
# ( 0, 1, 1) --> 1607067 [ 0 + 4400 Gregorian years] | |
# ( -1, 1, 1) --> 1606702 | |
# | |
# (-3999,12,31) --> 146827 [ exhaustively verified lower bound ] | |
# | |
# (-4399, 1, 1) --> 366 [and that is the soft lower bound] | |
# all intervals are clopen so do not use this as a spec: | |
# (-4400, 3, 1) --> 60 [and that is the hard lower bound] | |
# | |
# daynumber requires 22 bits (for this date range) | |
# hour,min,sec requires 17 bits (for one day) | |
# 39 bits (for date and time-of-day) | |
# | |
# timezone num requires 9 bits | |
# 48 bits (for date, time-of-day, timezone) | |
# | |
# millisecs requires 10 bits | |
# or year requires 13 bits | |
# this function with annotations is nearby eof | |
# | |
const adjust_monthdays = Int32[ 365, 396, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ]; | |
function ymd_to_daynumber(y::Int32, m::Int32, d::Int32) | |
k0::Int32 = 0; k1::Int32 = 1; k2::Int32 = 2; k3::Int32 = 3 | |
k32::Int32 = 32; k365::Int32 = 365; k4400::Int32 = 4400 | |
k42949673::Int32 = 42949673 | |
y = y + k4400 | |
y = y + ifelse(m >= k3, k0, k1) | |
d = d + (k365 * y) | |
y100 = ((k42949673 * y) >> k32) | |
d = d + (y >> k2) - y100 + (y100 >> k2) | |
d = d + adjust_monthdays[m] | |
return d | |
end | |
ymd_to_daynumber(yr::Int64, mo::Int64, dy::Int64) = | |
ymd_to_daynumber(yr%Int32, mo%Int32, dy%Int32) | |
# this function with annotations is nearby eof | |
# | |
function daynumber_to_ymd(daynum::Int64) | |
K = Y = M = D = 0 | |
daynum = daynum + 182562 | |
K = div( (daynum<<2), 146097 ) | |
daynum = daynum - ( (146097*K + 3) >> 2 ) | |
Y = div( 4000*(daynum+1), 1461001 ) | |
daynum = daynum - ( ((1461*Y) >> 2) - 31 ) | |
M = div( (80*daynum), 2447 ) | |
D = daynum - div( (2447*M), 80 ) | |
daynum = div( M, 11 ) | |
M = M + ( 2 - (12*daynum) ) | |
Y = Y + ( (100*(K-49)) + daynum) | |
return Y%Int32, M%Int32, D%Int32 | |
end | |
daynumber_to_ymd(daynum::Int32) = | |
daynumber_to_ymd( daynum%Int64 ) | |
#> | |
# | |
# the same annotated | |
# my sculpting shown | |
# | |
#< | |
#= | |
function ymd_to_daynumber(y::Int32, m::Int32, d::Int32) | |
# if (m<3) | |
# y-= 1; y+=4400 | |
# else | |
# y += 4400 | |
# end | |
# | |
# )to) | |
# | |
# if (m<3) y += 4399 else y += 4400 end; | |
# | |
# )to) | |
y += 4400 | |
y -= (m >= 3) ? 0 : 1 | |
d += (365*y) | |
# assert(y >= 0) | |
# tally leap years through year y | |
# ( +udiv4(y) -udiv100(y) +udiv400(y) ) | |
# | |
# )to) | |
y100 = (y * 42949673) >> 32 | |
d += (y>>2) - y100 + (y100 >> 2) | |
# int64(d + monthdays[m] + (365*y) + (y >>> 2) - y100 + ((y100 >> 2) - 32) | |
# | |
# )to) | |
# | |
# d += ( div(((152*m)-2),5) with entries 13,14 folded into 1,2) - 32 | |
# monthdays = [ 365, 396, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ] | |
# | |
# )to) | |
d += [ 365, 396, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ][m] | |
int64(d) | |
end | |
=# | |
#= | |
this is a date-shifted version of the | |
the Fliegel and van Flandern code [ACM Vol 11, 1968] | |
function daynumber_to_ymd(daynum::Int64) | |
# daynum -= 2286008 # untranslate Day Number (1607067 -32 +678973) | |
# daynum = daynum + 2400001 + 68569 | |
daynum += 182562 | |
# K = div(4*daynum, 146097)-3 | |
K = div( (daynum<<2), 146097 ) | |
#daynum = daynum - div((146097*K + 3), 4) | |
daynum -= ((146097*K + 3) >> 2) | |
Y = div(4000*(daynum+1), 1461001) | |
#daynum = daynum - div(1461*Y, 4) + 31 | |
daynum -= (((1461*Y) >> 2) - 31) | |
M = div(80*daynum, 2447) | |
D = daynum - div(2447*M,80) | |
daynum = div(M,11) | |
#M = M + 2 - 12*daynum | |
M += (2 - 12*daynum) | |
#Y = 100*(K-49) + Y + daynum | |
Y += 100*(K-49) + daynum | |
return Y%nt32, M%Int32, D%Int32 | |
end | |
=# | |
end # module DayNumber |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment