Hide keyboard shortcuts

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. 

3 

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. 

8 

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. 

13 

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. 

17 

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. 

26 

27A function to test if a given Gregorian calendar year is a leap year is 

28defined. 

29 

30Zero point of Modified Julian Date (MJD) and the MJD of 2000/1/1 

3112:00:00 are also given. 

32 

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. 

36 

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 

44 

45__version__ = "1.4.1" 

46 

47MJD_0 = 2400000.5 

48MJD_JD2000 = 51544.5 

49 

50 

51def ipart(x): 

52 """Return integer part of given number.""" 

53 return math.modf(x)[1] 

54 

55 

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) 

61 

62 # Divisible by 4 and, 

63 # either not divisible by 100 or divisible by 400. 

64 return not x and (y or not z) 

65 

66 

67def gcal2jd(year, month, day): 

68 """Gregorian calendar date to Julian date. 

69 

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. 

73 

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. 

82 

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. 

89 

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) 

114 

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. 

117 

118 >>> gcal2jd(2000, -2, -4) 

119 (2400000.5, 51447.0) 

120 >>> gcal2jd(1999, 9, 26) 

121 (2400000.5, 51447.0) 

122 

123 >>> gcal2jd(2000, 2, -1) 

124 (2400000.5, 51573.0) 

125 >>> gcal2jd(2000, 1, 30) 

126 (2400000.5, 51573.0) 

127 

128 >>> gcal2jd(2000, 3, -1) 

129 (2400000.5, 51602.0) 

130 >>> gcal2jd(2000, 2, 28) 

131 (2400000.5, 51602.0) 

132 

133 Month 0 becomes previous month. 

134 

135 >>> gcal2jd(2000, 0, 1) 

136 (2400000.5, 51513.0) 

137 >>> gcal2jd(1999, 12, 1) 

138 (2400000.5, 51513.0) 

139 

140 Day number 0 becomes last day of previous month. 

141 

142 >>> gcal2jd(2000, 3, 0) 

143 (2400000.5, 51603.0) 

144 >>> gcal2jd(2000, 2, 29) 

145 (2400000.5, 51603.0) 

146 

147 If `day` is greater than the number of days in `month`, then it 

148 gets carried over to the next month. 

149 

150 >>> gcal2jd(2000,2,30) 

151 (2400000.5, 51604.0) 

152 >>> gcal2jd(2000,3,1) 

153 (2400000.5, 51604.0) 

154 

155 >>> gcal2jd(2001,2,30) 

156 (2400000.5, 51970.0) 

157 >>> gcal2jd(2001,3,2) 

158 (2400000.5, 51970.0) 

159 

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. 

168 

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. 

171 

172 Negative numbers can be used for `month` and `day`. For example 

173 2000, -1, 1 is the same as 1999, 11, 1. 

174 

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. 

178 

179 The input values are truncated to integers. 

180 

181 """ 

182 year = int(year) 

183 month = int(month) 

184 day = int(day) 

185 

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 

192 

193 jd -= 0.5 # 0 hours; above JD is for midday, switch to midnight. 

194 

195 return MJD_0, jd 

196 

197 

198def jd2gcal(jd1, jd2): 

199 """Julian date to Gregorian calendar date and time of day. 

200 

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. 

204 

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. 

212 

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. 

219 

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) 

226 

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. 

229 

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) 

238 

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) 

251 

252 Notes 

253 ----- 

254 The last element of the tuple is the same as 

255 

256 (hh + mm / 60.0 + ss / 3600.0) / 24.0 

257 

258 where hh, mm, and ss are the hour, minute and second of the day. 

259 

260 See Also 

261 -------- 

262 gcal2jd 

263 

264 """ 

265 from math import modf 

266 

267 jd1_f, jd1_i = modf(jd1) 

268 jd2_f, jd2_i = modf(jd2) 

269 

270 jd_i = jd1_i + jd2_i 

271 

272 f = jd1_f + jd2_f 

273 

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 

284 

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 

295 

296 return int(year), int(month), int(day), f 

297 

298 

299def jcal2jd(year, month, day): 

300 """Julian calendar date to Julian date. 

301 

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. 

305 

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. 

314 

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. 

321 

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) 

343 

344 Notes 

345 ----- 

346 Unlike `gcal2jd`, negative months and days can result in incorrect 

347 Julian dates. 

348 

349 """ 

350 year = int(year) 

351 month = int(month) 

352 day = int(day) 

353 

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. 

360 

361 jd -= 0.5 # Convert midday to midnight. 

362 

363 return MJD_0, jd 

364 

365 

366def jd2jcal(jd1, jd2): 

367 """Julian calendar date for the given Julian date. 

368 

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. 

372 

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. 

380 

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. 

387 

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) 

394 

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) 

407 

408 """ 

409 from math import modf 

410 

411 jd1_f, jd1_i = modf(jd1) 

412 jd2_f, jd2_i = modf(jd2) 

413 

414 jd_i = jd1_i + jd2_i 

415 

416 f = jd1_f + jd2_f 

417 

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 

428 

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 

439 

440 return int(year), int(month), int(day), f