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#!/usr/local/bin/python 

2# encoding: utf-8 

3""" 

4*Convert times between various epochs and units* 

5 

6:Author: 

7 David Young 

8""" 

9from __future__ import division 

10from past.utils import old_div 

11from builtins import object 

12import sys 

13import os 

14os.environ['TERM'] = 'vt100' 

15from fundamentals import tools 

16 

17class conversions(object): 

18 """ 

19 *The worker class for the conversions module* 

20 

21 **Key Arguments** 

22 

23 - ``log`` -- logger 

24 - ``settings`` -- the settings dictionary 

25  

26 

27 **Usage** 

28 

29 .. todo:: 

30 

31 - add usage info 

32 - create a sublime snippet for usage 

33 - add mjd_to_date 

34 - add decimal_day_to_day_hour_min_sec 

35 - add date_to_mjd 

36 - convert all functions in __init__ to modules 

37 

38 ```python 

39 usage code  

40 ``` 

41  

42 """ 

43 # Initialisation 

44 

45 def __init__( 

46 self, 

47 log, 

48 settings=False, 

49 ): 

50 self.log = log 

51 log.debug("instansiating a new 'conversions' object") 

52 self.settings = settings 

53 # xt-self-arg-tmpx 

54 

55 return None 

56 

57 def get(self): 

58 """ 

59 *get the conversions object* 

60 

61 **Return** 

62 

63 - ``conversions`` 

64  

65 

66 .. todo:: 

67 

68 - @review: when complete, clean get method 

69 - @review: when complete add logging 

70 """ 

71 self.log.debug('starting the ``get`` method') 

72 

73 conversions = None 

74 

75 self.log.debug('completed the ``get`` method') 

76 return conversions 

77 

78 def ut_datetime_to_mjd( 

79 self, 

80 utDatetime): 

81 """*ut datetime to mjd* 

82 

83 If the date given has no time associated with it (e.g. ``20160426``), then the datetime assumed is ``20160426 00:00:00.0``. 

84 

85 Precision should be respected.  

86 

87 **Key Arguments** 

88 

89 - ``utDatetime`` -- UT datetime. Can accept various formats e.g. ``201604261444``, ``20160426``, ``20160426144444.5452``, ``2016-04-26 14:44:44.234``, ``20160426 14h44m44.432s``  

90  

91 

92 **Return** 

93 

94 - ``mjd`` -- the MJD 

95  

96 

97 .. todo :: 

98 

99 - replace getMJDFromSqlDate in all code 

100 

101 **Usage** 

102 

103 ```python 

104 from astrocalc.times import conversions 

105 converter = conversions( 

106 log=log 

107 ) 

108 mjd = converter.ut_datetime_to_mjd(utDatetime="20160426t1446") 

109 print(mjd) 

110 

111 # OUT: 57504.6153 

112 

113 mjd = converter.ut_datetime_to_mjd(utDatetime="2016-04-26 14:44:44.234") 

114 print(mjd) 

115 

116 # OUT: 57504.61440 

117 ``` 

118  

119 """ 

120 self.log.debug('starting the ``ut_datetime_to_mjd`` method') 

121 

122 import time 

123 import re 

124 mjd = None 

125 

126 # TRIM WHITESPACE FROM AROUND STRING 

127 utDatetime = utDatetime.strip() 

128 

129 # DATETIME REGEX 

130 matchObject = re.match( 

131 r'^(?P<year>\d{4})\D?(?P<month>(0\d|1[0-2]))\D?(?P<day>([0-2]\d|3[0-1])(\.\d+)?)(\D?(?P<hours>([0-1]\d|2[0-3]))\D?(?P<minutes>\d{2})(\D?(?P<seconds>\d{2}(\.\d*?)?))?)?s?$', utDatetime) 

132 

133 # RETURN ERROR IF REGEX NOT MATCHED 

134 if not matchObject: 

135 self.log.error( 

136 'UT Datetime is not in a recognised format. Input value was `%(utDatetime)s`' % locals()) 

137 raise IOError( 

138 'UT Datetime is not in a recognised format. Input value was `%(utDatetime)s`' % locals()) 

139 

140 year = matchObject.group("year") 

141 month = matchObject.group("month") 

142 day = matchObject.group("day") 

143 hours = matchObject.group("hours") 

144 minutes = matchObject.group("minutes") 

145 seconds = matchObject.group("seconds") 

146 

147 # CLEAN NUMBERS AND SET OUTPUT PRECISION 

148 if "." in day: 

149 fhours = (float(day) - int(float(day))) * 24 

150 hours = int(fhours) 

151 fminutes = (fhours - hours) * 60 

152 minutes = int(fminutes) 

153 seconds = fhours - minutes 

154 precision = len(repr(day).split(".")[-1]) 

155 elif not hours: 

156 hours = "00" 

157 minutes = "00" 

158 seconds = "00" 

159 precision = 1 

160 elif not seconds: 

161 seconds = "00" 

162 # PRECISION TO NEAREST MIN i.e. 0.000694444 DAYS 

163 precision = 4 

164 else: 

165 if "." not in seconds: 

166 precision = 5 

167 else: 

168 decLen = len(seconds.split(".")[-1]) 

169 precision = 5 + decLen 

170 

171 # CONVERT VALUES TO FLOAT 

172 seconds = float(seconds) 

173 year = float(year) 

174 month = float(month) 

175 day = float(day) 

176 hours = float(hours) 

177 minutes = float(minutes) 

178 

179 # DETERMINE EXTRA TIME (SMALLER THAN A SEC) 

180 extraTime = 0. 

181 if "." in repr(seconds): 

182 extraTime = old_div(float("." + repr(seconds).split(".") 

183 [-1]), (24. * 60. * 60.)) 

184 

185 # CONVERT TO UNIXTIME THEN MJD 

186 t = (int(year), int(month), int(day), int(hours), 

187 int(minutes), int(seconds), 0, 0, 0) 

188 unixtime = int(time.mktime(t)) 

189 mjd = (old_div(unixtime, 86400.0) - 2400000.5 + 2440587.5) + extraTime 

190 

191 mjd = "%0.*f" % (precision, mjd) 

192 

193 self.log.debug('completed the ``ut_datetime_to_mjd`` method') 

194 return mjd 

195 

196 def mjd_to_ut_datetime( 

197 self, 

198 mjd, 

199 sqlDate=False, 

200 datetimeObject=False): 

201 """*mjd to ut datetime* 

202 

203 Precision should be respected.  

204 

205 **Key Arguments** 

206 

207 - ``mjd`` -- time in MJD. 

208 - ``sqlDate`` -- add a 'T' between date and time instead of space 

209 - ``datetimeObject`` -- return a datetime object instead of a string. Default *False* 

210  

211 

212 .. todo:: 

213 

214 - replace getDateFromMJD in all code 

215 - replace getSQLDateFromMJD in all code 

216 

217 **Return** 

218 

219 - ``utDatetime`` - the UT datetime in string format 

220  

221 

222 **Usage** 

223 

224 ```python 

225 from astrocalc.times import conversions 

226 converter = conversions( 

227 log=log 

228 ) 

229 utDate = converter.mjd_to_ut_datetime( 

230 mjd=57504.61577585013 

231 ) 

232 print(utDate) 

233 

234 # OUT: 2016-04-26 14:46:43.033 

235 

236 utDate = converter.mjd_to_ut_datetime( 

237 mjd=57504.61577585013, 

238 sqlDate=True 

239 ) 

240 print(utDate) 

241 

242 # OUT: 2016-04-26T14:46:43.033 

243 ``` 

244  

245 """ 

246 self.log.debug('starting the ``mjd_to_ut_datetime`` method') 

247 

248 from datetime import datetime 

249 

250 # CONVERT TO UNIXTIME 

251 unixtime = (float(mjd) + 2400000.5 - 2440587.5) * 86400.0 

252 theDate = datetime.utcfromtimestamp(unixtime) 

253 

254 if datetimeObject == False: 

255 # DETERMINE PRECISION 

256 strmjd = repr(mjd) 

257 if "." not in strmjd: 

258 precisionUnit = "day" 

259 precision = 0 

260 utDatetime = theDate.strftime("%Y-%m-%d") 

261 else: 

262 lenDec = len(strmjd.split(".")[-1]) 

263 if lenDec < 2: 

264 precisionUnit = "day" 

265 precision = 0 

266 utDatetime = theDate.strftime("%Y-%m-%d") 

267 elif lenDec < 3: 

268 precisionUnit = "hour" 

269 precision = 0 

270 utDatetime = theDate.strftime("%Y-%m-%d") 

271 elif lenDec < 5: 

272 precisionUnit = "minute" 

273 precision = 0 

274 utDatetime = theDate.strftime("%Y-%m-%d %H:%M") 

275 else: 

276 precisionUnit = "second" 

277 precision = lenDec - 5 

278 if precision > 3: 

279 precision = 3 

280 secs = float(theDate.strftime("%S.%f")) 

281 secs = "%02.*f" % (precision, secs) 

282 utDatetime = theDate.strftime("%Y-%m-%d %H:%M:") + secs 

283 

284 if sqlDate: 

285 utDatetime = utDatetime.replace(" ", "T") 

286 else: 

287 utDatetime = theDate 

288 

289 self.log.debug('completed the ``mjd_to_ut_datetime`` method') 

290 return utDatetime 

291 

292 def decimal_day_to_day_hour_min_sec( 

293 self, 

294 daysFloat): 

295 """*Convert a day from decimal format to hours mins and sec* 

296 

297 Precision should be respected.  

298 

299 **Key Arguments** 

300 

301 - ``daysFloat`` -- the day as a decimal. 

302  

303 

304 **Return** 

305 

306 - ``daysInt`` -- day as an integer 

307 - ``hoursInt`` -- hour as an integer (None if input precsion too low) 

308 - ``minsInt`` -- mins as an integer (None if input precsion too low) 

309 - ``secFloat`` -- secs as a float (None if input precsion too low) 

310  

311 

312 **Usage** 

313 

314 .. todo:: 

315 

316 - replace `decimal_day_to_day_hour_min_sec` in all other code 

317 

318 ```python 

319 from astrocalc.times import conversions 

320 converter = conversions( 

321 log=log 

322 ) 

323 daysInt, hoursInt, minsInt, secFloat = converter.decimal_day_to_day_hour_min_sec( 

324 daysFloat=24.2453 

325 ) 

326 print(daysInt, hoursInt, minsInt, secFloat) 

327 

328 # OUTPUT: 24, 5, 53, None 

329 

330 daysInt, hoursInt, minsInt, secFloat = converter.decimal_day_to_day_hour_min_sec( 

331 daysFloat=24.1232435454 

332 ) 

333 print("%(daysInt)s days, %(hoursInt)s hours, %(minsInt)s mins, %(secFloat)s sec" % locals()) 

334 

335 # OUTPUT: 24 days, 2 hours, 57 mins, 28.242 sec 

336 ``` 

337  

338 """ 

339 self.log.debug( 

340 'completed the ````decimal_day_to_day_hour_min_sec`` method') 

341 

342 daysInt = int(daysFloat) 

343 hoursFloat = (daysFloat - daysInt) * 24. 

344 hoursInt = int(hoursFloat) 

345 minsFloat = (hoursFloat - hoursInt) * 60. 

346 minsInt = int(minsFloat) 

347 secFloat = (minsFloat - minsInt) * 60. 

348 

349 # DETERMINE PRECISION 

350 strday = repr(daysFloat) 

351 if "." not in strday: 

352 precisionUnit = "day" 

353 precision = 0 

354 hoursInt = None 

355 minsInt = None 

356 secFloat = None 

357 else: 

358 lenDec = len(strday.split(".")[-1]) 

359 if lenDec < 2: 

360 precisionUnit = "day" 

361 precision = 0 

362 hoursInt = None 

363 minsInt = None 

364 secFloat = None 

365 elif lenDec < 3: 

366 precisionUnit = "hour" 

367 precision = 0 

368 minsInt = None 

369 secFloat = None 

370 elif lenDec < 5: 

371 precisionUnit = "minute" 

372 precision = 0 

373 secFloat = None 

374 else: 

375 precisionUnit = "second" 

376 precision = lenDec - 5 

377 if precision > 3: 

378 precision = 3 

379 secFloat = "%02.*f" % (precision, secFloat) 

380 

381 self.log.debug( 

382 'completed the ``decimal_day_to_day_hour_min_sec`` method') 

383 return daysInt, hoursInt, minsInt, secFloat 

384 

385 # use the tab-trigger below for new method 

386 # xt-class-method