Source code for timelinelib.calendar.gregorian.gregorian2julian
# -*- coding: utf-8 -*-
# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Rickard Lindberg, Roger Lindberg
#
# This file is part of Timeline.
#
# Timeline 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.
#
# Timeline 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 Timeline. If not, see <http://www.gnu.org/licenses/>.
"""
Contains the GregorianDateTime class and static functions related
to the class.
:doc:`Tests are found here <unit_calendar_gregorian_gregorian>`.
"""
from timelinelib.calendar.gregorian.time import GregorianTime
[docs]def gregorian_ymd_to_julian_day(year, month, day):
"""
This algorithm is described here:
* http://www.tondering.dk/claus/cal/julperiod.php#formula
* http://en.wikipedia.org/wiki/Julian_day#Converting_Julian_or_Gregorian_calendar_date_to_Julian_Day_Number
Integer division works differently in C and in Python for negative numbers.
C truncates towards 0 and Python truncates towards negative infinity:
http://python-history.blogspot.se/2010/08/why-pythons-integer-division-floors.html
The above sources don't state which to be used. If we can prove that
division-expressions are always positive, we can be sure this algorithm
works the same in C and in Python.
We must prove that:
1) y >= 0
2) ((153 * m) + 2) >= 0
Let's prove 1):
y = year + 4800 - a
= year + 4800 - ((14 - month) // 12)
year >= -4713 (gives a julian day of 0)
so
year + 4800 >= -4713 + 4800 = 87
The expression ((14 - month) // 12) varies between 0 and 1 when month
varies between 1 and 12. Therefore y >= 87 - 1 = 86, and 1) is proved.
Let's prove 2):
m = month + (12 * a) - 3
= month + (12 * ((14 - month) // 12)) - 3
1 <= month <= 12
m(1) = 1 + (12 * ((14 - 1) // 12)) - 3 = 1 + (12 * 1) - 3 = 10
m(2) = 2 + (12 * ((14 - 2) // 12)) - 3 = 2 + (12 * 1) - 3 = 11
m(3) = 3 + (12 * ((14 - 3) // 12)) - 3 = 3 + (12 * 0) - 3 = 0
m(4) = 4 + (12 * ((14 - 4) // 12)) - 3 = 4 + (12 * 0) - 3 = 1
m(5) = 5 + (12 * ((14 - 5) // 12)) - 3 = 5 + (12 * 0) - 3 = 2
m(6) = 6 + (12 * ((14 - 6) // 12)) - 3 = 6 + (12 * 0) - 3 = 3
m(7) = 7 + (12 * ((14 - 7) // 12)) - 3 = 7 + (12 * 0) - 3 = 4
m(8) = 8 + (12 * ((14 - 8) // 12)) - 3 = 8 + (12 * 0) - 3 = 5
m(9) = 9 + (12 * ((14 - 9) // 12)) - 3 = 9 + (12 * 0) - 3 = 6
m(10) = 10 + (12 * ((14 - 10) // 12)) - 3 = 10 + (12 * 0) - 3 = 7
m(11) = 11 + (12 * ((14 - 11) // 12)) - 3 = 11 + (12 * 0) - 3 = 8
m(12) = 12 + (12 * ((14 - 12) // 12)) - 3 = 12 + (12 * 0) - 3 = 9
So, m is always > 0. Which also makes the expression ((153 * m) + 2) > 0,
and 2) is proved.
"""
a = (14 - month) // 12
y = year + 4800 - a
m = month + (12 * a) - 3
julian_day = (day
+ (((153 * m) + 2) // 5)
+ (y * 365)
+ (y // 4)
- (y // 100)
+ (y // 400)
- 32045)
if julian_day < GregorianTime.MIN_JULIAN_DAY:
raise ValueError("gregorian_ymd_to_julian_day only works for julian days >= %d, but was %d" % (
GregorianTime.MIN_JULIAN_DAY, julian_day))
return julian_day
[docs]def gregorian_ymd_to_julian_day_alt(year, month, day):
"""
Table 15.14 Selected arithmetic calendars, with parameters for algorithms
Calendar a y j m n r p q v u s t w A B C
1 Egyptian 3968 47 0 13 1 365 0 0 1 30 0 0
2 Ethiopian 4720 124 0 13 4 1461 0 3 1 30 0 0
3 Coptic 4996 124 0 13 4 1461 0 3 1 30 0 0
4 Republican b 6504 111 0 13 4 1461 0 3 1 30 0 0 396 578797 −51
5 Julian 4716 1401 2 12 4 1461 0 3 5 153 2 2
6 Gregorian 4716 1401 2 12 4 1461 0 3 5 153 2 2 184 274277 −38
7 Civil Islamic 5519 7664 0 12 30 10631 14 15 100 2951 51 10
8 Baha’i ´ c 6560 1412 19 20 4 1461 0 3 1 19 0 0 184 274273 −50
9 Saka 4794 1348 1 12 4 1461 0 3 1 31 0 0 184 274073 −36
Algorithm 3. To convert a date D/M/Y in one of the calendars listed in Table 15.14 to a
Julian Day Number, J:
1. h = M − m
2. g = Y + y − (n − h)/n
3. f = mod(h − 1+ n, n)
4. e = (p ∗ g + q)/r + D − 1− j
5. J = e + (s ∗ f + t)/u
6. J = J − (3 ∗ ((g + A)/100))/4 − C
"""
y = 4716
j = 1401
m = 2
n = 12
r = 4
p = 1461
q = 0
v = 3
u = 5
s = 153
t = 2
w = 2
A = 184
B = 274277
C = -38
h = month - m
g = year + y - (n - h) // n
f = (h - 1 + n) % n
e = (p * g + q) // r + day - 1 - j
julian_day = e + (s * f + t) // u
julian_day = julian_day - (3 * ((g + A) // 100)) // 4 - C
return julian_day