Skip to content

Instantly share code, notes, and snippets.

@markhamilton1
Created December 30, 2014 02:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markhamilton1/381b722093cb5f73f67e to your computer and use it in GitHub Desktop.
Save markhamilton1/381b722093cb5f73f67e to your computer and use it in GitHub Desktop.
The date time module for my AstroScript library.
import math
import sio
import time
DATE_DELIMITER = ','
DATE_PROMPT = "Enter a date"
DATE_FORMAT = "yr, mo, dy"
DATE_HELP = "No help available."
DATE_INVALID = "The entered date is invalid!"
DATETIME_PROMPT = "Enter a date-time"
DATETIME_FORMAT = "yr, mo, dy, hr, mn, sc, md"
DATETIME_HELP = "No help available."
DATETIME_INVALID = "The entered date-time is invalid!"
LONGITUDE_PROMPT = "Enter a longitude (-W|+E)"
LONGITUDE_FORMAT = "###.##"
LONGITUDE_HELP = "No help available."
LONGITUDE_INVALID = "The entered longitude is invalid!"
LATITUDE_PROMPT = "Enter a latitude (+N|-S)"
LATITUDE_FORMAT = "##.##"
LATITUDE_HELP = "No help available."
LATITUDE_INVALID = "The entered latitude is invalid!"
ZONE_CORRECTION_PROMPT = "Enter a zone correction (-W|+E)"
ZONE_CORRECTION_FORMAT = "##"
ZONE_CORRECTION_HELP = "No help available."
ZONE_CORRECTION_INVALID = "The entered zone correction is invalid!"
DAYS_OF_WEEK = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
LENGTH_OF_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
TIME_MODES = ['lct', 'ut', 'td', 'gst', 'lst']
DAYLIGHT_SAVINGS = True
ZONE_CORRECTION = 0 # - for west, + for east
LONGITUDE = 0 # - for west, + for east
LATITUDE = 0 # + for north, - for south
DATETIME_PRINT_FORMAT = '%b %d, %Y %H:%M:%S'
DATE_DELTA_T_VALUES = \
[
124.0, 119.0, 115.0, 110.0, 106.0, 102.0, 98.0, 95.0, 91.0, 88.0, # 1620
85.0, 82.0, 79.0, 77.0, 74.0, 72.0, 70.0, 67.0, 65.0, 63.0, # 1630
62.0, 60.0, 58.0, 57.0, 55.0, 54.0, 53.0, 51.0, 50.0, 49.0, # 1640
48.0, 47.0, 46.0, 45.0, 44.0, 43.0, 42.0, 41.0, 40.0, 38.0, # 1650
37.0, 36.0, 35.0, 34.0, 33.0, 32.0, 31.0, 30.0, 28.0, 27.0, # 1660
26.0, 25.0, 24.0, 23.0, 22.0, 21.0, 20.0, 19.0, 18.0, 17.0, # 1670
16.0, 15.0, 14.0, 14.0, 13.0, 12.0, 12.0, 11.0, 11.0, 10.0, # 1680
10.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, # 1690
10.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 10.0, 10.0, # 1700
10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 11.0, 11.0, 11.0, # 1710
11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, # 1720
11.0, 11.0, 11.0, 11.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, # 1730
12.0, 12.0, 12.0, 12.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, # 1740
13.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 15.0, 15.0, # 1750
15.0, 15.0, 15.0, 15.0, 15.0, 16.0, 16.0, 16.0, 16.0, 16.0, # 1760
16.0, 16.0, 16.0, 16.0, 16.0, 17.0, 17.0, 17.0, 17.0, 17.0, # 1770
17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, # 1780
17.0, 17.0, 16.0, 16.0, 16.0, 16.0, 15.0, 15.0, 14.0, 14.0, # 1790
13.7, 13.4, 13.1, 12.9, 12.7, 12.6, 12.5, 12.5, 12.5, 12.5, # 1800
12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.4, 12.3, 12.2, # 1810
12.0, 11.7, 11.4, 11.1, 10.6, 10.2, 9.6, 9.1, 8.6, 8.0, # 1820
7.5, 7.0, 6.6, 6.3, 6.0, 5.8, 5.7, 5.6, 5.6, 5.6, # 1830
5.7, 5.8, 5.9, 6.1, 6.2, 6.3, 6.5, 6.6, 6.8, 6.9, # 1840
7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.7, 7.8, 7.8, # 1850
7.88, 7.82, 7.54, 6.97, 6.40, 6.02, 5.41, 4.10, 2.92, 1.81, # 1860
1.61, 0.10, -1.02, -1.28, -2.69, -3.24, -3.64, -4.54, -4.71, -5.11, # 1870
-5.40, -5.42, -5.20, -5.46, -5.46, -5.79, -5.63, -5.64, -5.80, -5.66, # 1880
-5.87, -6.01, -6.19, -6.64, -6.44, -6.47, -6.09, -5.76, -4.66, -3.74, # 1890
-2.72, -1.54, -0.02, 1.24, 2.64, 3.86, 5.37, 6.14, 7.75, 9.13, # 1900
10.46, 11.53, 13.36, 14.65, 16.01, 17.20, 18.24, 19.06, 20.25, 20.95, # 1910
21.16, 22.25, 22.41, 23.03, 23.49, 23.62, 23.86, 24.49, 24.34, 24.08, # 1920
24.02, 24.00, 23.87, 23.95, 23.86, 23.93, 23.73, 23.92, 23.96, 24.02, # 1930
24.33, 24.83, 25.30, 25.70, 26.24, 26.77, 27.28, 27.78, 28.25, 28.71, # 1940
29.15, 29.57, 29.97, 30.36, 30.72, 31.07, 31.35, 31.68, 32.18, 32.68, # 1950
33.15, 33.59, 34.00, 34.47, 35.03, 35.73, 36.54, 37.43, 38.29, 39.20, # 1960
40.18, 41.17, 42.23, 43.37, 44.4841, 45.4761, 46.4567, 47.5214, 48.5344, 49.5861, # 1970
50.5387, 51.3808, 52.1668, 52.9565, 53.7882, 54.3427, 54.8712, 55.3222, 55.8197, 56.30, # 1980
56.8553, 57.5653, 58.3092, 59.1218, 59.9845, 60.7853, 61.6287, 62.2950, 62.9659, 63.4473, # 1990
63.8285, 64.0908, 64.2998, 64.4734, 64.5736, 64.6876, 64.8452, 65.1464, 65.4574, 65.7768, # 2000
66.0699, 66.3246, 66.6030, 67.1, 67.6, 68.0, 69.0, 69.0, 69.0, 70.0, # 2010
70.0, 71.0 # 2020
]
DATE_TD_YEAR_MIN = 1620
DATE_TD_YEAR_MAX = 2021
def _calc_td_dt(dat):
if (dat[0] < DATE_TD_YEAR_MIN - 70) or (dat[0] > DATE_TD_YEAR_MAX + 70):
julian = to_julian_from_date_tuple(dat)
dY = julian - 2382148.0
dT = ((dY * dY) / 41048480.0) - 15.0
elif dat[0] < DATE_TD_YEAR_MIN:
m = (DATE_DELTA_T_VALUES[1] - DATE_DELTA_T_VALUES[0]) / 2.0
dT = ((dat[0] - DATE_TD_YEAR_MIN) * m) + DATE_DELTA_T_VALUES[0]
elif dat[0] > DATE_TD_YEAR_MAX:
last = (DATE_TD_YEAR_MAX - DATE_TD_YEAR_MIN) / 2
m = (DATE_DELTA_T_VALUES[last] - DATE_DELTA_T_VALUES[last - 1]) / 2.0
dT = ((dat[0] - DATE_TD_YEAR_MAX) * m) + DATE_DELTA_T_VALUES[last]
else:
i = dat[0] - DATE_TD_YEAR_MIN
dT = DATE_DELTA_T_VALUES[i]
return dT
def _convert_date_time(res):
dat = []
i = 0
while (i < len(res)) and (i < 7):
if i < 6:
dat.append(int(res[i]))
else:
dat.append(res[i])
i += 1
return dat
def add_days(dat, dd):
"""
Add the day delta to the date.
:param dat: date tuple to adjust (year, month, day[, hours, mins, secs[, mode]])
:param dd: day delta
:return: adjusted date tuple (year, month, day[, hours, mins, secs[, mode]])
"""
if validate_date(dat, require_time=False):
ldat = len(dat)
j = to_julian_from_date_tuple(dat)
dat = to_date_tuple_from_julian(j + dd)
return dat[0:ldat]
raise ValueError, "Invalid date!"
def add_months(dat, dm):
"""
Add the month delta to the date.
:param dat: date tuple to adjust (year, month, day[, hours, mins, secs[, mode]])
:param dm: month delta
:return: adjusted date tuple (year, month, day[, hours, mins, secs[, mode]])
"""
if validate_date(dat, require_time=False):
m = dat[1] + dm
dy = 0
while m < 1:
dy -= 1
m += 12
while m > 12:
dy += 1
m -= 12
dat[1] = m
return add_years(dat, dy)
raise ValueError, "Invalid date!"
def add_years(dat, dy):
"""
Add the year delta to the date.
:param dat: date tuple to adjust (year, month, day[, hours, mins, secs[, mode]])
:param dy: year delta
:return: adjusted date tuple (year, month, day[, hours, mins, secs[, mode]])
"""
if validate_date(dat, require_time=False):
dat[0] += dy
raise ValueError, "Invalid date!"
def get_date_of_easter(year):
"""
Calculate the date of Easter.
:param year: year for which to calculate the date of Easter
:return: date tuple for Easter (None if not a valid year)(year, month, day)
"""
if (year is not None) and (year >= 1583):
a = int(year % 19)
b = int(year / 100)
c = int(year % 100)
d = int(b / 4)
e = int(b % 4)
f = int((b + 8) / 25)
g = int((b - f + 1) / 3)
h = int(((19 * a) + b - d - g + 15) % 30)
i = int(c / 4)
k = int(c % 4)
l = int((32 + (2 * e) + (2 * i) - h - k ) % 7)
m = int((a + (11 * h) + (22 * l) ) / 451)
t = int((h + l - (7 * m) + 114))
n = int(t / 31)
p = int((t % 31) + 1)
return year, n, p
return None
def get_days_in_month(dat):
"""
Determine the number of days in the specified month.
:param dat: date tuple (year, month, day[, hours, mins, secs[, mode]])
:return: number of days in the month (0=error)
"""
d = 0
if validate_date(dat, require_time=False):
d = LENGTH_OF_MONTH[dat[1]]
if (dat[1] == 2) and is_leap_year(dat[0]):
d += 1
return d
raise ValueError, "Invalid date!"
def is_leap_year(year):
"""
Determine if the specified year is a leap year.
:param year: the year to test
:return: True or False
"""
if year is not None:
year = int(year)
if (year % 100) == 0:
return (year % 400) == 0
return (year % 4) == 0
raise ValueError, "Invalid year!"
def now():
"""
Get a date tuple of the current date and time.
:return: date tuple with the current date and time (year, month, day, hours, minutes, seconds, mode)
"""
current = time.time()
dat = time.gmtime(current)
# dat = (year, month, day, hour, min, sec, weekday, julian day, daylight savings flag)
return dat[0], dat[1], dat[2], dat[3], dat[4], dat[5], 'ut'
def print_pretty_date(label, dat, newline=True):
"""
Print the date date tuple as a properly formatted date string
:param label: the label to prepend
:param dat: the date tuple to use
:param newline: a boolean indicating if a newline should be added
"""
s = to_pretty_date(dat)
if s:
sio.print_labeled_text(label, s, newline=newline)
def read_date(default_date=None, prompt=DATE_PROMPT, format=DATE_FORMAT):
"""
Read a date tuple.
:param default_date: the default date tuple to use
:param prompt: the prompt to use (optional)
:param format: the format to use (optional)
:return: the date tuple (year, month, day[, hours, minutes, seconds, mode])
"""
while True:
res = sio.read_delimited_line(DATE_DELIMITER, prompt, None, format, default_date)
if (type(res) is str) and (len(res) == 0):
return None
if (type(res) is str) and (len(res) == 1) and (res[0] == '?'):
sio.print_newline()
sio.print_text(DATE_HELP)
sio.print_newline()
elif (type(res) is str) and (len(res) == 1) and (res[0] == '*'):
return now()
else:
dat = _convert_date_time(res)
if not validate_date(dat, False):
sio.print_newline()
sio.print_text(DATE_INVALID)
sio.print_newline()
else:
return dat
def read_datetime(default_datetime=None, prompt=DATETIME_PROMPT, format=DATETIME_FORMAT):
"""
Read a date time tuple.
:param default_datetime: the default date time tuple to use
:param prompt: the prompt to use (optional)
:param format: the format to use (optional)
:return: the date time tuple (year, month, day[, hours, minutes, seconds, mode])
"""
while True:
res = sio.read_delimited_line(DATE_DELIMITER, prompt, None, format, default_datetime)
if (type(res) is str) and (len(res) == 0):
return None
if (type(res) is str) and (len(res) == 1) and (res[0] == '?'):
sio.print_newline()
sio.print_text(DATETIME_HELP)
sio.print_newline()
elif (type(res) is str) and (len(res) == 1) and (res[0] == '*'):
return now()
else:
dat = _convert_date_time(res)
if not validate_date(dat, True):
sio.print_newline()
sio.print_text(DATETIME_INVALID)
sio.print_newline()
else:
return dat
def read_latitude(default_latitude=None, prompt=LATITUDE_PROMPT, format=LATITUDE_FORMAT):
"""
Read a latitude.
:param default_latitude: the default latitude to use
:param prompt: the prompt to use (optional)
:param format: the format to use (optional)
:return: the latitude
"""
while True:
res = sio.read_line(prompt, None, format, default_latitude)
if not len(res):
return None
if len(res) == 1:
if res[0] == '?':
sio.print_newline()
sio.print_text(LATITUDE_HELP)
sio.print_newline()
else:
try:
lat = float(res)
if abs(lat) <= 90.0:
return lat
except Exception:
pass
sio.print_newline()
sio.print_text(LATITUDE_INVALID)
sio.print_newline()
def read_longitude(default_longitude=None, prompt=LONGITUDE_PROMPT, format=LONGITUDE_FORMAT):
"""
Read a longitude.
:param default_longitude: the default longitude to use
:param prompt: the prompt to use (optional)
:param format: the format to use (optional)
:return: the longitude
"""
while True:
res = sio.read_line(prompt, None, format, default_longitude)
if not len(res):
return None
if len(res) == 1:
if res[0] == '?':
sio.print_newline()
sio.print_text(LONGITUDE_HELP)
sio.print_newline()
else:
try:
lng = float(res)
if abs(lng) <= 360.0:
return lng
except Exception:
pass
sio.print_newline()
sio.print_text(LONGITUDE_INVALID)
sio.print_newline()
def read_zone_correction(default_zone_correction=None, prompt=ZONE_CORRECTION_PROMPT, format=ZONE_CORRECTION_FORMAT):
"""
Read a time zone correction.
:param default_zone_correction: the default time zone correction to use
:param prompt: the prompt to use (optional)
:param format: the format to use (optional)
:return: the zone correction
"""
while True:
res = sio.read_line(prompt, None, format, default_zone_correction)
if not len(res):
return None
if len(res) == 1:
if res[0] == '?':
sio.print_newline()
sio.print_text(ZONE_CORRECTION_HELP)
sio.print_newline()
else:
try:
zc = int(res)
if abs(zc) <= 24:
return zc
except Exception:
pass
sio.print_newline()
sio.print_text(ZONE_CORRECTION_INVALID)
sio.print_newline()
def set_daylight_savings(daylight_savings):
"""
Set the daylight savings to be used in date calculations.
:param daylight_savings: True=daylight savings
"""
global DAYLIGHT_SAVINGS
if daylight_savings is not None:
DAYLIGHT_SAVINGS = daylight_savings
def set_latitude(latitude):
"""
Set the latitude to be used in date calculations.
:param latitude: the latitude to set (- for west, + for east)
"""
global LATITUDE
if latitude is not None:
latitude = sio.to_float(latitude)
while latitude <= -90.0:
latitude += 90.0
while latitude >= 90.0:
latitude -= 90.0
LATITUDE = latitude
def set_longitude(longitude):
"""
Set the longitude to be used in date calculations.
:param longitude: the longitude to set (- for west, + for east)
"""
global LONGITUDE
if longitude is not None:
longitude = sio.to_float(longitude)
while longitude <= -360.0:
longitude += 360.0
while longitude >= 360.0:
longitude -= 360.0
LONGITUDE = longitude
def set_zone_correction(zc):
"""
Set the time zone correction to be used in date calculations.
:param zc: the time zone correction to set (- for west, + for east)
"""
global ZONE_CORRECTION
if zc is not None:
zc = sio.to_int(zc)
if zc < -24:
zc = -24
elif zc > 24:
zc = 24
ZONE_CORRECTION = zc
def to_pretty_date(dat, format=DATETIME_PRINT_FORMAT):
"""
Convert the date tuple to a formatted date.
:param dat: the date tuple to use
:return: the formatted date string (or None if error)
"""
s = ""
if validate_date(dat):
t = (int(dat[0]), int(dat[1]), int(dat[2]), int(dat[3]), int(dat[4]), int(dat[5]), 0, 0, 0)
s = time.strftime(format, t)
if len(dat) > 6:
s += ' ' + dat[6].upper()
return s
def to_date_tuple_from_julian(jul, mode='ut'):
"""
Converts a julian day to a date tuple.
:param jul: julian
:param mode: time mode (default: 'ut')
:return: date tuple (year, month, day, hours, minutes, seconds, mode)
"""
if jul is not None:
jd = 0.5 + jul
I = int(jd)
F = jd - I
if I > 2229160:
A = int((I - 1867216.25) / 36524.25)
B = I + 1 + A - int(A / 4.0)
else:
B = I
C = B + 1524
D = int((C - 122.1) / 365.25)
E = int(365.25 * D)
G = int((C - E) / 30.6001)
d = C - E + F - int(30.6001 * G)
if G < 13.5:
month = G - 1
else:
month = G - 13
if month > 2.5:
year = D - 4716
else:
year = D - 4715
day = int(d)
h = (d - day) * 24
hour, minute, sec = to_time_tuple_from_hours(h)
return year, month, day, hour, minute, sec, mode
raise ValueError, "Invalid julian date!"
def to_day_of_week_from_julian(jul):
"""
Converts a julian to day of the week.
:param jul: julian
:return: day of week
"""
global DAYS_OF_WEEK
if jul is not None:
a = (jul + 1.5) / 7.0
day = int(round((a - int(a)) * 7.0))
return day - 1
raise ValueError, "Invalid julian date!"
def to_gst(dat):
"""
Converts to greenwich sidereal time.
:param dat: the date time tuple to use
:return: the converted date time tuple (None if error)
"""
global LONGITUDE
if validate_date(dat):
if (dat[6] == 'td') or (dat[6] == 'lct'):
dat = to_ut(dat)
if dat[6] == 'ut':
j = to_julian_from_date_tuple(dat[0:3])
S = j - 2451545.0
T = S / 36525.0
T0 = 6.697374558 + (T * (2400.051336 + (0.000025862 * T)))
while T0 >= 24.0:
T0 -= 24.0
while T0 < 0.0:
T0 += 24.0
t = to_hours_from_time_tuple(dat[3:6])
t *= 1.002737909
t += T0
if t >= 24.0:
t -= 24.0
tim = to_time_tuple_from_hours(t)
dat = dat[0], dat[1], dat[2], tim[0], tim[1], tim[2], 'gst'
if dat[6] == 'lst':
t = to_hours_from_time_tuple(dat[3:6])
t -= LONGITUDE / 15.0
if t >= 24.0:
t -= 24.0
elif t < 0.0:
t += 24.0
tim = to_time_tuple_from_hours(t)
dat = dat[0], dat[1], dat[2], tim[0], tim[1], tim[2], 'gst'
return dat
raise ValueError, "Invalid date!"
def to_hours_from_time_tuple(tim):
"""
Converts a time tuple to decimal hours.
:param tim: time tuple (hours, mins, secs)
:return: dhours
"""
if validate_time(tim):
hour, min, sec = tim
if hour < 0:
mult = -1
else:
mult = 1
return mult * (abs(hour) + ((sec / 60.0) + min) / 60.0)
raise ValueError, "Invalid time!"
def to_julian_from_date_tuple(dat):
"""
Converts a date tuple to julian day.
:param dat: date tuple (year, month, day[, hours, mins, secs[, mode]])
:return: julian
"""
if validate_date(dat, require_time=False):
if len(dat) == 7:
year, month, day, hour, min, sec, mode = dat
elif len(dat) == 6:
year, month, day, hour, min, sec = dat
elif len(dat) == 3:
year, month, day = dat
hour, min, sec = 0, 0, 0
else:
raise ValueError, "Invalid date!"
if month <= 2:
year -= 1
month += 12
if year >= 1582:
A = year / 100
B = 2 - A + (A / 4)
else:
B = 0
if year < 0:
C = int((365.25 * year) - 0.75)
else:
C = int(365.25 * year)
D = int(30.6001 * (month + 1))
return 1720994.5 + B + C + D + day + ((((sec / 60.0) + float(min)) / 60.0) + float(hour)) / 24.0
def to_lct(dat):
"""
Converts to local civil time.
:param dat: the date time tuple to use
:return: the converted date time tuple
"""
global DAYLIGHT_SAVINGS, ZONE_CORRECTION
if validate_date(dat):
if (dat[6] == 'td') or (dat[6] == 'lst') or (dat[6] == 'gst'):
dat = to_ut(dat)
if dat[6] == 'ut':
t = to_hours_from_time_tuple(dat[3:6])
t += ZONE_CORRECTION
if DAYLIGHT_SAVINGS:
t += 1
if t >= 24.0:
t -= 24.0
dat = add_days(dat, 1)
elif t < 0.0:
t += 24.0
dat = add_days(dat, -1)
tim = to_time_tuple_from_hours(t)
dat = dat[0], dat[1], dat[2], tim[0], tim[1], tim[2], 'lct'
return dat
raise ValueError, "Invalid date!"
def to_lst(dat):
"""
Converts to local sidereal time.
:param dat: the date time tuple to use
:return: the converted date time tuple
"""
global LONGITUDE
if validate_date(dat):
if dat[6] == 'td':
dat = to_ut(dat)
if (dat[6] == 'lct') or (dat[6] == 'ut'):
dat = to_gst(dat)
if dat[6] == 'gst':
t = to_hours_from_time_tuple(dat[3:6])
t += LONGITUDE / 15.0
if t >= 24.0:
t -= 24.0
elif t < 0.0:
t += 24.0
tim = to_time_tuple_from_hours(t)
dat = dat[0], dat[1], dat[2], tim[0], tim[1], tim[2], 'lst'
return dat
raise ValueError, "Invalid date!"
def to_td(dat):
"""
Converts to dynamical time.
:param dat: the date time tuple to use
:return: the converted date time tuple
"""
if validate_date(dat):
if dat[6] != 'td':
dat = to_ut(dat)
dt = _calc_td_dt(dat) / 86400.0
td_j = to_julian_from_date_tuple(dat) + dt
dat = to_date_tuple_from_julian(td_j, 'td')
return dat
raise ValueError, "Invalid date!"
def to_time_tuple_from_hours(dhours):
"""
Converts decimal hours to a time tuple.
:param dhours: decimal hours to convert
:return: time tuple (hours, mins, secs)
"""
if dhours is not None:
hour = int(dhours)
dmins = abs(dhours - hour) * 60
min = int(dmins)
sec = round((dmins - min) * 60, 2)
return hour, min, sec
raise ValueError, "Invalid decimal hours!"
def to_ut(dat):
"""
Converts to universal time.
:param dat: the date time tuple to use
:return: the converted date time tuple
"""
global DAYLIGHT_SAVINGS, ZONE_CORRECTION
if validate_date(dat):
if dat[6] == 'lct':
t = to_hours_from_time_tuple(dat[3:6])
if DAYLIGHT_SAVINGS:
t -= 1
t -= ZONE_CORRECTION
if t >= 24.0:
t -= 24.0
dat = add_days(dat, 1)
elif t < 0.0:
t += 24.0
dat = add_days(dat, -1)
tim = to_time_tuple_from_hours(t)
dat = dat[0], dat[1], dat[2], tim[0], tim[1], tim[2], 'ut'
if dat[6] == 'lst':
dat = to_gst(dat)
if dat[6] == 'gst':
j = to_julian_from_date_tuple(dat)
j -= (j - int(j)) - 0.5
S = float(j) - 2451545.0
T = float(S) / 36525.0
T0 = 6.697374558 + (T * (2400.051336 + (0.000025862 * T)))
while T0 >= 24.0:
T0 -= 24.0
while T0 < 0.0:
T0 += 24.0
t = to_hours_from_time_tuple(dat[3:6])
t -= T0
while t < 0.0:
t += 24.0
t *= 0.9972695663
tim = to_time_tuple_from_hours(t)
dat = dat[0], dat[1], dat[2], tim[0], tim[1], tim[2], 'ut'
if dat[6] == 'td':
t = _calc_td_dt(dat) / 86400.0
j = to_julian_from_date_tuple(dat)
dat = to_date_tuple_from_julian(j - t, 'ut')
return dat
raise ValueError, "Invalid date!"
def validate_date(dat, require_time=True):
"""
Validate a date or date time tuple.
:param dat: the date tuple to validate
:return: True=valid, False=invalid
"""
global LENGTH_OF_MONTH
if (dat is not None) and (len(dat) >= 3):
yr = sio.to_int(dat[0])
mth = sio.to_int(dat[1])
day = sio.to_int(dat[2])
if not validate_month(mth):
return False
if is_leap_year(yr) and (mth == 2):
if day > 29:
return False
elif day > LENGTH_OF_MONTH[mth]:
return False
if len(dat) > 3:
if not validate_time(dat[3:]):
return False
elif require_time:
return False
return True
return False
def validate_month(month):
"""
Validate a month.
:param month: the month to validate
:return: True=valid, False=invalid
"""
if month is not None:
month = sio.to_int(month)
if month < 1:
return False
if month <= 12:
return True
return False
def validate_time(tim):
"""
Validate a time tuple.
:param tim: the time tuple to validate
:return: True=valid, False=invalid
"""
global TIME_MODES
if (tim is not None) and (len(tim) >= 3):
hrs = sio.to_int(tim[0])
mns = sio.to_int(tim[1])
scs = sio.to_int(tim[2])
if (hrs >= 0) and (hrs < 24):
if (mns >= 0) and (mns < 60):
if (scs >= 0) and (scs < 60):
if len(tim) == 4:
md = tim[3]
if md in TIME_MODES:
return True
else:
return True
return False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment