Created
December 30, 2014 02:23
-
-
Save markhamilton1/381b722093cb5f73f67e to your computer and use it in GitHub Desktop.
The date time module for my AstroScript library.
This file contains hidden or 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
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