# Copyright Brandon Stafford
#
# This file is part of Pysolar.
#
# Pysolar is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Pysolar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Pysolar. If not, see .
"""This file contains functions related to time conversion.
"""
import warnings
import sys
import datetime
import time
from .constants import \
seconds_per_day
from pysolar.tzinfo_check import check_aware_dt
julian_day_offset = 1721425 - 0.5 # add to datetime.datetime.toordinal() to get Julian day number
gregorian_day_offset = 719163 # number of days to add to datetime.datetime.timestamp() / seconds_per_day to agree with datetime.datetime.toordinal()
tt_offset = 32.184 # seconds to add to TAI to get TT
#+
# Table of leap-seconds (to date) taken from Wikipedia
# .
#-
leap_seconds_base_year = 1972
leap_seconds_adjustments = \
[ # two entries per year starting from 1972, first for 23:59:59 June 30,
# second for 23:59:59 December 31. +1 indicates that 23:59:60 follows,
# -1 indicates that 23:59:59 does not exist, not that the latter has ever occurred.
# source: https://www.nist.gov/pml/time-and-frequency-division/atomic-standards/leap-second-and-ut1-utc-information
(+1, +1), # 1972
(0, +1), # 1973
(0, +1), # 1974
(0, +1), # 1975
(0, +1), # 1976
(0, +1), # 1977
(0, +1), # 1978
(0, +1), # 1979
(0, 0), # 1980
(+1, 0), # 1981
(+1, 0), # 1982
(+1, 0), # 1983
(0, 0), # 1984
(+1, 0), # 1985
(0, 0), # 1986
(0, +1), # 1987
(0, 0), # 1988
(0, +1), # 1989
(0, +1), # 1990
(0, 0), # 1991
(+1, 0), # 1992
(+1, 0), # 1993
(+1, 0), # 1994
(0, +1), # 1995
(0, 0), # 1996
(+1, 0), # 1997
(0, +1), # 1998
(0, 0), # 1999
(0, 0), # 2000
(0, 0), # 2001
(0, 0), # 2002
(0, 0), # 2003
(0, 0), # 2004
(0, +1), # 2005
(0, 0), # 2006
(0, 0), # 2007
(0, +1), # 2008
(0, 0), # 2009
(0, 0), # 2010
(0, 0), # 2011
(+1, 0), # 2012
(0, 0), # 2013
(0, 0), # 2014
(+1, 0), # 2015
(0, +1), # 2016
(0, 0), # 2017
(0, 0), # 2018
(0, 0), # 2019
(0, 0), # 2020
]
@check_aware_dt('when')
def get_leap_seconds(when) :
"returns adjustment to be added to UTC at the specified datetime to produce TAI."
when = when.utctimetuple()
adj = 10 # as decreed from 1972
year = leap_seconds_base_year
while True :
if year > when.tm_year :
break
if year - leap_seconds_base_year >= len(leap_seconds_adjustments) :
if (
when.tm_year - leap_seconds_base_year > len(leap_seconds_adjustments)
or
when.tm_year - leap_seconds_base_year == len(leap_seconds_adjustments)
and
when.tm_mon > 6
) :
warnings.warn \
(
"I don't know about leap seconds after %d"
%
(leap_seconds_base_year + len(leap_seconds_adjustments) - 1)
)
#end if
break
#end if
entry = leap_seconds_adjustments[year - leap_seconds_base_year]
if year == when.tm_year :
if when.tm_mon > 6 :
adj += entry[0]
#end if
break
#end if
adj += entry[0] + entry[1]
year += 1
#end while
return \
adj
#end get_leap_seconds
# table of values to add to UT1 to get TT (to date), generated by util/get_delta_t script
delta_t_base_year = 1973
delta_t_base_month = 2
delta_t = \
[
[ # 1973
43.4724, # 2
43.5648, # 3
43.6737, # 4
43.7782, # 5
43.8763, # 6
43.9562, # 7
44.0315, # 8
44.1132, # 9
44.1982, # 10
44.2952, # 11
44.3936, # 12
],
[ # 1974
44.4841, # 1
44.5646, # 2
44.6425, # 3
44.7386, # 4
44.8370, # 5
44.9302, # 6
44.9986, # 7
45.0584, # 8
45.1284, # 9
45.2064, # 10
45.2980, # 11
45.3897, # 12
],
[ # 1975
45.4761, # 1
45.5633, # 2
45.6450, # 3
45.7375, # 4
45.8284, # 5
45.9133, # 6
45.9820, # 7
46.0408, # 8
46.1067, # 9
46.1825, # 10
46.2789, # 11
46.3713, # 12
],
[ # 1976
46.4567, # 1
46.5445, # 2
46.6311, # 3
46.7302, # 4
46.8284, # 5
46.9247, # 6
46.9970, # 7
47.0709, # 8
47.1451, # 9
47.2362, # 10
47.3413, # 11
47.4319, # 12
],
[ # 1977
47.5214, # 1
47.6049, # 2
47.6837, # 3
47.7781, # 4
47.8771, # 5
47.9687, # 6
48.0348, # 7
48.0942, # 8
48.1608, # 9
48.2460, # 10
48.3439, # 11
48.4355, # 12
],
[ # 1978
48.5344, # 1
48.6325, # 2
48.7294, # 3
48.8365, # 4
48.9353, # 5
49.0319, # 6
49.1013, # 7
49.1591, # 8
49.2286, # 9
49.3070, # 10
49.4018, # 11
49.4945, # 12
],
[ # 1979
49.5862, # 1
49.6805, # 2
49.7602, # 3
49.8556, # 4
49.9489, # 5
50.0347, # 6
50.1019, # 7
50.1622, # 8
50.2260, # 9
50.2968, # 10
50.3831, # 11
50.4599, # 12
],
[ # 1980
50.5387, # 1
50.6161, # 2
50.6866, # 3
50.7658, # 4
50.8454, # 5
50.9187, # 6
50.9761, # 7
51.0278, # 8
51.0843, # 9
51.1538, # 10
51.2319, # 11
51.3063, # 12
],
[ # 1981
51.3808, # 1
51.4526, # 2
51.5160, # 3
51.5985, # 4
51.6809, # 5
51.7573, # 6
51.8133, # 7
51.8532, # 8
51.9014, # 9
51.9603, # 10
52.0328, # 11
52.0985, # 12
],
[ # 1982
52.1668, # 1
52.2316, # 2
52.2938, # 3
52.3680, # 4
52.4465, # 5
52.5180, # 6
52.5752, # 7
52.6178, # 8
52.6668, # 9
52.7340, # 10
52.8056, # 11
52.8792, # 12
],
[ # 1983
52.9565, # 1
53.0445, # 2
53.1268, # 3
53.2197, # 4
53.3024, # 5
53.3747, # 6
53.4335, # 7
53.4778, # 8
53.5300, # 9
53.5845, # 10
53.6523, # 11
53.7256, # 12
],
[ # 1984
53.7882, # 1
53.8367, # 2
53.8830, # 3
53.9443, # 4
54.0042, # 5
54.0536, # 6
54.0856, # 7
54.1084, # 8
54.1463, # 9
54.1914, # 10
54.2452, # 11
54.2958, # 12
],
[ # 1985
54.3427, # 1
54.3911, # 2
54.4320, # 3
54.4898, # 4
54.5456, # 5
54.5977, # 6
54.6355, # 7
54.6532, # 8
54.6776, # 9
54.7174, # 10
54.7741, # 11
54.8253, # 12
],
[ # 1986
54.8713, # 1
54.9161, # 2
54.9581, # 3
54.9997, # 4
55.0476, # 5
55.0912, # 6
55.1132, # 7
55.1328, # 8
55.1532, # 9
55.1898, # 10
55.2416, # 11
55.2838, # 12
],
[ # 1987
55.3222, # 1
55.3613, # 2
55.4063, # 3
55.4629, # 4
55.5111, # 5
55.5524, # 6
55.5812, # 7
55.6004, # 8
55.6262, # 9
55.6656, # 10
55.7168, # 11
55.7698, # 12
],
[ # 1988
55.8197, # 1
55.8615, # 2
55.9130, # 3
55.9663, # 4
56.0220, # 5
56.0700, # 6
56.0939, # 7
56.1105, # 8
56.1314, # 9
56.1611, # 10
56.2068, # 11
56.2583, # 12
],
[ # 1989
56.3000, # 1
56.3399, # 2
56.3790, # 3
56.4283, # 4
56.4804, # 5
56.5352, # 6
56.5697, # 7
56.5983, # 8
56.6328, # 9
56.6739, # 10
56.7332, # 11
56.7972, # 12
],
[ # 1990
56.8553, # 1
56.9111, # 2
56.9755, # 3
57.0471, # 4
57.1136, # 5
57.1738, # 6
57.2226, # 7
57.2597, # 8
57.3073, # 9
57.3643, # 10
57.4334, # 11
57.5016, # 12
],
[ # 1991
57.5653, # 1
57.6333, # 2
57.6973, # 3
57.7711, # 4
57.8407, # 5
57.9058, # 6
57.9576, # 7
57.9975, # 8
58.0426, # 9
58.1043, # 10
58.1679, # 11
58.2389, # 12
],
[ # 1992
58.3092, # 1
58.3833, # 2
58.4537, # 3
58.5401, # 4
58.6228, # 5
58.6917, # 6
58.7410, # 7
58.7836, # 8
58.8406, # 9
58.8986, # 10
58.9714, # 11
59.0438, # 12
],
[ # 1993
59.1218, # 1
59.2003, # 2
59.2747, # 3
59.3574, # 4
59.4434, # 5
59.5242, # 6
59.5850, # 7
59.6344, # 8
59.6928, # 9
59.7588, # 10
59.8386, # 11
59.9111, # 12
],
[ # 1994
59.9845, # 1
60.0564, # 2
60.1231, # 3
60.2042, # 4
60.2804, # 5
60.3530, # 6
60.4012, # 7
60.4440, # 8
60.4900, # 9
60.5578, # 10
60.6324, # 11
60.7059, # 12
],
[ # 1995
60.7853, # 1
60.8664, # 2
60.9387, # 3
61.0277, # 4
61.1103, # 5
61.1870, # 6
61.2454, # 7
61.2881, # 8
61.3378, # 9
61.4036, # 10
61.4760, # 11
61.5525, # 12
],
[ # 1996
61.6287, # 1
61.6846, # 2
61.7433, # 3
61.8132, # 4
61.8823, # 5
61.9497, # 6
61.9969, # 7
62.0343, # 8
62.0714, # 9
62.1202, # 10
62.1810, # 11
62.2382, # 12
],
[ # 1997
62.2950, # 1
62.3506, # 2
62.3995, # 3
62.4754, # 4
62.5463, # 5
62.6136, # 6
62.6571, # 7
62.6942, # 8
62.7383, # 9
62.7926, # 10
62.8567, # 11
62.9146, # 12
],
[ # 1998
62.9659, # 1
63.0217, # 2
63.0807, # 3
63.1462, # 4
63.2053, # 5
63.2599, # 6
63.2844, # 7
63.2961, # 8
63.3126, # 9
63.3422, # 10
63.3871, # 11
63.4339, # 12
],
[ # 1999
63.4673, # 1
63.4979, # 2
63.5319, # 3
63.5679, # 4
63.6104, # 5
63.6444, # 6
63.6642, # 7
63.6739, # 8
63.6926, # 9
63.7147, # 10
63.7518, # 11
63.7927, # 12
],
[ # 2000
63.8285, # 1
63.8557, # 2
63.8804, # 3
63.9075, # 4
63.9393, # 5
63.9691, # 6
63.9799, # 7
63.9833, # 8
63.9938, # 9
64.0093, # 10
64.0400, # 11
64.0670, # 12
],
[ # 2001
64.0908, # 1
64.1068, # 2
64.1282, # 3
64.1584, # 4
64.1833, # 5
64.2094, # 6
64.2117, # 7
64.2073, # 8
64.2116, # 9
64.2223, # 10
64.2500, # 11
64.2761, # 12
],
[ # 2002
64.2998, # 1
64.3192, # 2
64.3450, # 3
64.3735, # 4
64.3943, # 5
64.4151, # 6
64.4132, # 7
64.4118, # 8
64.4097, # 9
64.4168, # 10
64.4329, # 11
64.4511, # 12
],
[ # 2003
64.4734, # 1
64.4893, # 2
64.5053, # 3
64.5269, # 4
64.5471, # 5
64.5597, # 6
64.5512, # 7
64.5371, # 8
64.5359, # 9
64.5415, # 10
64.5544, # 11
64.5654, # 12
],
[ # 2004
64.5736, # 1
64.5891, # 2
64.6015, # 3
64.6176, # 4
64.6374, # 5
64.6549, # 6
64.6530, # 7
64.6379, # 8
64.6372, # 9
64.6400, # 10
64.6543, # 11
64.6723, # 12
],
[ # 2005
64.6876, # 1
64.7052, # 2
64.7313, # 3
64.7575, # 4
64.7811, # 5
64.8001, # 6
64.7995, # 7
64.7876, # 8
64.7831, # 9
64.7921, # 10
64.8096, # 11
64.8311, # 12
],
[ # 2006
64.8452, # 1
64.8597, # 2
64.8850, # 3
64.9175, # 4
64.9480, # 5
64.9794, # 6
64.9895, # 7
65.0028, # 8
65.0138, # 9
65.0371, # 10
65.0773, # 11
65.1122, # 12
],
[ # 2007
65.1464, # 1
65.1833, # 2
65.2145, # 3
65.2494, # 4
65.2921, # 5
65.3279, # 6
65.3413, # 7
65.3452, # 8
65.3496, # 9
65.3711, # 10
65.3972, # 11
65.4296, # 12
],
[ # 2008
65.4573, # 1
65.4868, # 2
65.5152, # 3
65.5450, # 4
65.5781, # 5
65.6127, # 6
65.6288, # 7
65.6370, # 8
65.6493, # 9
65.6760, # 10
65.7097, # 11
65.7461, # 12
],
[ # 2009
65.7768, # 1
65.8025, # 2
65.8237, # 3
65.8595, # 4
65.8973, # 5
65.9323, # 6
65.9509, # 7
65.9534, # 8
65.9628, # 9
65.9839, # 10
66.0147, # 11
66.0420, # 12
],
[ # 2010
66.0699, # 1
66.0961, # 2
66.1310, # 3
66.1683, # 4
66.2072, # 5
66.2356, # 6
66.2409, # 7
66.2335, # 8
66.2349, # 9
66.2441, # 10
66.2751, # 11
66.3054, # 12
],
[ # 2011
66.3246, # 1
66.3406, # 2
66.3624, # 3
66.3957, # 4
66.4289, # 5
66.4619, # 6
66.4749, # 7
66.4751, # 8
66.4829, # 9
66.5056, # 10
66.5383, # 11
66.5706, # 12
],
[ # 2012
66.6030, # 1
66.6340, # 2
66.6569, # 3
66.6925, # 4
66.7289, # 5
66.7579, # 6
66.7708, # 7
66.7740, # 8
66.7846, # 9
66.8103, # 10
66.8400, # 11
66.8779, # 12
],
[ # 2013
66.9069, # 1
66.9443, # 2
66.9763, # 3
67.0258, # 4
67.0716, # 5
67.1100, # 6
67.1266, # 7
67.1331, # 8
67.1458, # 9
67.1718, # 10
67.2091, # 11
67.2460, # 12
],
[ # 2014
67.2810, # 1
67.3136, # 2
67.3457, # 3
67.3890, # 4
],
] # delta_t
@check_aware_dt('when')
def get_delta_t(when) :
"returns a suitable value for delta_t for the given datetime."
when = when.utctimetuple()
year, month = when.tm_year, when.tm_mon
if year < delta_t_base_year :
year = delta_t_base_year
month = 1
elif year == delta_t_base_year :
month = max(0, month - delta_t_base_month) + 1
elif year >= delta_t_base_year + len(delta_t) :
year = delta_t_base_year + len(delta_t) - 1
#end if
if year == delta_t_base_year + len(delta_t) - 1 :
month = min(month, len(delta_t[year - delta_t_base_year]))
#end if
return \
delta_t[year - delta_t_base_year][month - 1]
# don't bother doing any fancy interpolation
#end get_delta_t
@check_aware_dt('when')
def get_julian_solar_day(when):
"returns the UT Julian day number (including fraction of a day) corresponding to" \
" the specified date/time. This version assumes the proleptic Gregorian calendar;" \
" trying to adjust for pre-Gregorian dates/times seems pointless when the changeover" \
" happened over such wildly varying times in different regions."
return \
(
(when.timestamp() + get_leap_seconds(when) + tt_offset - get_delta_t(when))
/
seconds_per_day
+
gregorian_day_offset
+
julian_day_offset
)
#end get_julian_solar_day
@check_aware_dt('when')
def get_julian_ephemeris_day(when) :
"returns the TT Julian day number (including fraction of a day) corresponding to" \
" the specified date/time. This version assumes the proleptic Gregorian calendar;" \
" trying to adjust for pre-Gregorian dates/times seems pointless when the changeover" \
" happened over such wildly varying times in different regions."
return \
(
(when.timestamp() + get_leap_seconds(when) + tt_offset)
/
seconds_per_day
+
gregorian_day_offset
+
julian_day_offset
)
#end get_julian_ephemeris_day
def get_julian_century(julian_day):
return (julian_day - 2451545.0) / 36525.0
def get_julian_ephemeris_century(julian_ephemeris_day):
return (julian_ephemeris_day - 2451545.0) / 36525.0
def get_julian_ephemeris_millennium(julian_ephemeris_century):
return (julian_ephemeris_century / 10.0)