Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/jdcal.py : 28%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding:utf-8 -*-
2"""Functions for converting between Julian dates and calendar dates.
4A function for converting Gregorian calendar dates to Julian dates, and
5another function for converting Julian calendar dates to Julian dates
6are defined. Two functions for the reverse calculations are also
7defined.
9Different regions of the world switched to Gregorian calendar from
10Julian calendar on different dates. Having separate functions for Julian
11and Gregorian calendars allow maximum flexibility in choosing the
12relevant calendar.
14All the above functions are "proleptic". This means that they work for
15dates on which the concerned calendar is not valid. For example,
16Gregorian calendar was not used prior to around October 1582.
18Julian dates are stored in two floating point numbers (double). Julian
19dates, and Modified Julian dates, are large numbers. If only one number
20is used, then the precision of the time stored is limited. Using two
21numbers, time can be split in a manner that will allow maximum
22precision. For example, the first number could be the Julian date for
23the beginning of a day and the second number could be the fractional
24day. Calculations that need the latter part can now work with maximum
25precision.
27A function to test if a given Gregorian calendar year is a leap year is
28defined.
30Zero point of Modified Julian Date (MJD) and the MJD of 2000/1/1
3112:00:00 are also given.
33This module is based on the TPM C library, by Jeffery W. Percival. The
34idea for splitting Julian date into two floating point numbers was
35inspired by the IAU SOFA C library.
37:author: Prasanth Nair
38:contact: prasanthhn@gmail.com
39:license: BSD (https://opensource.org/licenses/bsd-license.php)
40"""
41from __future__ import division
42from __future__ import print_function
43import math
45__version__ = "1.4.1"
47MJD_0 = 2400000.5
48MJD_JD2000 = 51544.5
51def ipart(x):
52 """Return integer part of given number."""
53 return math.modf(x)[1]
56def is_leap(year):
57 """Leap year or not in the Gregorian calendar."""
58 x = math.fmod(year, 4)
59 y = math.fmod(year, 100)
60 z = math.fmod(year, 400)
62 # Divisible by 4 and,
63 # either not divisible by 100 or divisible by 400.
64 return not x and (y or not z)
67def gcal2jd(year, month, day):
68 """Gregorian calendar date to Julian date.
70 The input and output are for the proleptic Gregorian calendar,
71 i.e., no consideration of historical usage of the calendar is
72 made.
74 Parameters
75 ----------
76 year : int
77 Year as an integer.
78 month : int
79 Month as an integer.
80 day : int
81 Day as an integer.
83 Returns
84 -------
85 jd1, jd2: 2-element tuple of floats
86 When added together, the numbers give the Julian date for the
87 given Gregorian calendar date. The first number is always
88 MJD_0 i.e., 2451545.5. So the second is the MJD.
90 Examples
91 --------
92 >>> gcal2jd(2000,1,1)
93 (2400000.5, 51544.0)
94 >>> 2400000.5 + 51544.0 + 0.5
95 2451545.0
96 >>> year = [-4699, -2114, -1050, -123, -1, 0, 1, 123, 1678.0, 2000,
97 ....: 2012, 2245]
98 >>> month = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
99 >>> day = [1, 12, 23, 14, 25, 16, 27, 8, 9, 10, 11, 31]
100 >>> x = [gcal2jd(y, m, d) for y, m, d in zip(year, month, day)]
101 >>> for i in x: print i
102 (2400000.5, -2395215.0)
103 (2400000.5, -1451021.0)
104 (2400000.5, -1062364.0)
105 (2400000.5, -723762.0)
106 (2400000.5, -679162.0)
107 (2400000.5, -678774.0)
108 (2400000.5, -678368.0)
109 (2400000.5, -633797.0)
110 (2400000.5, -65812.0)
111 (2400000.5, 51827.0)
112 (2400000.5, 56242.0)
113 (2400000.5, 141393.0)
115 Negative months and days are valid. For example, 2000/-2/-4 =>
116 1999/+12-2/-4 => 1999/10/-4 => 1999/9/30-4 => 1999/9/26.
118 >>> gcal2jd(2000, -2, -4)
119 (2400000.5, 51447.0)
120 >>> gcal2jd(1999, 9, 26)
121 (2400000.5, 51447.0)
123 >>> gcal2jd(2000, 2, -1)
124 (2400000.5, 51573.0)
125 >>> gcal2jd(2000, 1, 30)
126 (2400000.5, 51573.0)
128 >>> gcal2jd(2000, 3, -1)
129 (2400000.5, 51602.0)
130 >>> gcal2jd(2000, 2, 28)
131 (2400000.5, 51602.0)
133 Month 0 becomes previous month.
135 >>> gcal2jd(2000, 0, 1)
136 (2400000.5, 51513.0)
137 >>> gcal2jd(1999, 12, 1)
138 (2400000.5, 51513.0)
140 Day number 0 becomes last day of previous month.
142 >>> gcal2jd(2000, 3, 0)
143 (2400000.5, 51603.0)
144 >>> gcal2jd(2000, 2, 29)
145 (2400000.5, 51603.0)
147 If `day` is greater than the number of days in `month`, then it
148 gets carried over to the next month.
150 >>> gcal2jd(2000,2,30)
151 (2400000.5, 51604.0)
152 >>> gcal2jd(2000,3,1)
153 (2400000.5, 51604.0)
155 >>> gcal2jd(2001,2,30)
156 (2400000.5, 51970.0)
157 >>> gcal2jd(2001,3,2)
158 (2400000.5, 51970.0)
160 Notes
161 -----
162 The returned Julian date is for mid-night of the given date. To
163 find the Julian date for any time of the day, simply add time as a
164 fraction of a day. For example Julian date for mid-day can be
165 obtained by adding 0.5 to either the first part or the second
166 part. The latter is preferable, since it will give the MJD for the
167 date and time.
169 BC dates should be given as -(BC - 1) where BC is the year. For
170 example 1 BC == 0, 2 BC == -1, and so on.
172 Negative numbers can be used for `month` and `day`. For example
173 2000, -1, 1 is the same as 1999, 11, 1.
175 The Julian dates are proleptic Julian dates, i.e., values are
176 returned without considering if Gregorian dates are valid for the
177 given date.
179 The input values are truncated to integers.
181 """
182 year = int(year)
183 month = int(month)
184 day = int(day)
186 a = ipart((month - 14) / 12.0)
187 jd = ipart((1461 * (year + 4800 + a)) / 4.0)
188 jd += ipart((367 * (month - 2 - 12 * a)) / 12.0)
189 x = ipart((year + 4900 + a) / 100.0)
190 jd -= ipart((3 * x) / 4.0)
191 jd += day - 2432075.5 # was 32075; add 2400000.5
193 jd -= 0.5 # 0 hours; above JD is for midday, switch to midnight.
195 return MJD_0, jd
198def jd2gcal(jd1, jd2):
199 """Julian date to Gregorian calendar date and time of day.
201 The input and output are for the proleptic Gregorian calendar,
202 i.e., no consideration of historical usage of the calendar is
203 made.
205 Parameters
206 ----------
207 jd1, jd2: int
208 Sum of the two numbers is taken as the given Julian date. For
209 example `jd1` can be the zero point of MJD (MJD_0) and `jd2`
210 can be the MJD of the date and time. But any combination will
211 work.
213 Returns
214 -------
215 y, m, d, f : int, int, int, float
216 Four element tuple containing year, month, day and the
217 fractional part of the day in the Gregorian calendar. The first
218 three are integers, and the last part is a float.
220 Examples
221 --------
222 >>> jd2gcal(*gcal2jd(2000,1,1))
223 (2000, 1, 1, 0.0)
224 >>> jd2gcal(*gcal2jd(1950,1,1))
225 (1950, 1, 1, 0.0)
227 Out of range months and days are carried over to the next/previous
228 year or next/previous month. See gcal2jd for more examples.
230 >>> jd2gcal(*gcal2jd(1999,10,12))
231 (1999, 10, 12, 0.0)
232 >>> jd2gcal(*gcal2jd(2000,2,30))
233 (2000, 3, 1, 0.0)
234 >>> jd2gcal(*gcal2jd(-1999,10,12))
235 (-1999, 10, 12, 0.0)
236 >>> jd2gcal(*gcal2jd(2000, -2, -4))
237 (1999, 9, 26, 0.0)
239 >>> gcal2jd(2000,1,1)
240 (2400000.5, 51544.0)
241 >>> jd2gcal(2400000.5, 51544.0)
242 (2000, 1, 1, 0.0)
243 >>> jd2gcal(2400000.5, 51544.5)
244 (2000, 1, 1, 0.5)
245 >>> jd2gcal(2400000.5, 51544.245)
246 (2000, 1, 1, 0.24500000000261934)
247 >>> jd2gcal(2400000.5, 51544.1)
248 (2000, 1, 1, 0.099999999998544808)
249 >>> jd2gcal(2400000.5, 51544.75)
250 (2000, 1, 1, 0.75)
252 Notes
253 -----
254 The last element of the tuple is the same as
256 (hh + mm / 60.0 + ss / 3600.0) / 24.0
258 where hh, mm, and ss are the hour, minute and second of the day.
260 See Also
261 --------
262 gcal2jd
264 """
265 from math import modf
267 jd1_f, jd1_i = modf(jd1)
268 jd2_f, jd2_i = modf(jd2)
270 jd_i = jd1_i + jd2_i
272 f = jd1_f + jd2_f
274 # Set JD to noon of the current date. Fractional part is the
275 # fraction from midnight of the current date.
276 if -0.5 < f < 0.5:
277 f += 0.5
278 elif f >= 0.5:
279 jd_i += 1
280 f -= 0.5
281 elif f <= -0.5:
282 jd_i -= 1
283 f += 1.5
285 l = jd_i + 68569
286 n = ipart((4 * l) / 146097.0)
287 l -= ipart(((146097 * n) + 3) / 4.0)
288 i = ipart((4000 * (l + 1)) / 1461001)
289 l -= ipart((1461 * i) / 4.0) - 31
290 j = ipart((80 * l) / 2447.0)
291 day = l - ipart((2447 * j) / 80.0)
292 l = ipart(j / 11.0)
293 month = j + 2 - (12 * l)
294 year = 100 * (n - 49) + i + l
296 return int(year), int(month), int(day), f
299def jcal2jd(year, month, day):
300 """Julian calendar date to Julian date.
302 The input and output are for the proleptic Julian calendar,
303 i.e., no consideration of historical usage of the calendar is
304 made.
306 Parameters
307 ----------
308 year : int
309 Year as an integer.
310 month : int
311 Month as an integer.
312 day : int
313 Day as an integer.
315 Returns
316 -------
317 jd1, jd2: 2-element tuple of floats
318 When added together, the numbers give the Julian date for the
319 given Julian calendar date. The first number is always
320 MJD_0 i.e., 2451545.5. So the second is the MJD.
322 Examples
323 --------
324 >>> jcal2jd(2000, 1, 1)
325 (2400000.5, 51557.0)
326 >>> year = [-4699, -2114, -1050, -123, -1, 0, 1, 123, 1678, 2000,
327 ...: 2012, 2245]
328 >>> month = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12]
329 >>> day = [1, 12, 23, 14, 25, 16, 27, 8, 9, 10, 11, 31]
330 >>> x = [jcal2jd(y, m, d) for y, m, d in zip(year, month, day)]
331 >>> for i in x: print i
332 (2400000.5, -2395252.0)
333 (2400000.5, -1451039.0)
334 (2400000.5, -1062374.0)
335 (2400000.5, -723765.0)
336 (2400000.5, -679164.0)
337 (2400000.5, -678776.0)
338 (2400000.5, -678370.0)
339 (2400000.5, -633798.0)
340 (2400000.5, -65772.0)
341 (2400000.5, 51871.0)
342 (2400000.5, 56285.0)
344 Notes
345 -----
346 Unlike `gcal2jd`, negative months and days can result in incorrect
347 Julian dates.
349 """
350 year = int(year)
351 month = int(month)
352 day = int(day)
354 jd = 367 * year
355 x = ipart((month - 9) / 7.0)
356 jd -= ipart((7 * (year + 5001 + x)) / 4.0)
357 jd += ipart((275 * month) / 9.0)
358 jd += day
359 jd += 1729777 - 2400000.5 # Return 240000.5 as first part of JD.
361 jd -= 0.5 # Convert midday to midnight.
363 return MJD_0, jd
366def jd2jcal(jd1, jd2):
367 """Julian calendar date for the given Julian date.
369 The input and output are for the proleptic Julian calendar,
370 i.e., no consideration of historical usage of the calendar is
371 made.
373 Parameters
374 ----------
375 jd1, jd2: int
376 Sum of the two numbers is taken as the given Julian date. For
377 example `jd1` can be the zero point of MJD (MJD_0) and `jd2`
378 can be the MJD of the date and time. But any combination will
379 work.
381 Returns
382 -------
383 y, m, d, f : int, int, int, float
384 Four element tuple containing year, month, day and the
385 fractional part of the day in the Julian calendar. The first
386 three are integers, and the last part is a float.
388 Examples
389 --------
390 >>> jd2jcal(*jcal2jd(2000, 1, 1))
391 (2000, 1, 1, 0.0)
392 >>> jd2jcal(*jcal2jd(-4000, 10, 11))
393 (-4000, 10, 11, 0.0)
395 >>> jcal2jd(2000, 1, 1)
396 (2400000.5, 51557.0)
397 >>> jd2jcal(2400000.5, 51557.0)
398 (2000, 1, 1, 0.0)
399 >>> jd2jcal(2400000.5, 51557.5)
400 (2000, 1, 1, 0.5)
401 >>> jd2jcal(2400000.5, 51557.245)
402 (2000, 1, 1, 0.24500000000261934)
403 >>> jd2jcal(2400000.5, 51557.1)
404 (2000, 1, 1, 0.099999999998544808)
405 >>> jd2jcal(2400000.5, 51557.75)
406 (2000, 1, 1, 0.75)
408 """
409 from math import modf
411 jd1_f, jd1_i = modf(jd1)
412 jd2_f, jd2_i = modf(jd2)
414 jd_i = jd1_i + jd2_i
416 f = jd1_f + jd2_f
418 # Set JD to noon of the current date. Fractional part is the
419 # fraction from midnight of the current date.
420 if -0.5 < f < 0.5:
421 f += 0.5
422 elif f >= 0.5:
423 jd_i += 1
424 f -= 0.5
425 elif f <= -0.5:
426 jd_i -= 1
427 f += 1.5
429 j = jd_i + 1402.0
430 k = ipart((j - 1) / 1461.0)
431 l = j - (1461.0 * k)
432 n = ipart((l - 1) / 365.0) - ipart(l / 1461.0)
433 i = l - (365.0 * n) + 30.0
434 j = ipart((80.0 * i) / 2447.0)
435 day = i - ipart((2447.0 * j) / 80.0)
436 i = ipart(j / 11.0)
437 month = j + 2 - (12.0 * i)
438 year = (4 * k) + n + i - 4716.0
440 return int(year), int(month), int(day), f