#
source:
TI03-DataExtractor/trunk/pydxs/DateTimeManager.py
@
794

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI03-DataExtractor/trunk/pydxs/DateTimeManager.py@794
Revision 794, 11.0 KB checked in by astephen, 13 years ago (diff) |
---|

Rev | Line | |
---|---|---|

[794] | 1 | #!/usr/bin/env python |

2 | ||

3 | # Copyright (C) 2004 CCLRC & NERC( Natural Environment Research Council ). | |

4 | # This software may be distributed under the terms of the | |

5 | # Q Public License, version 1.0 or later. http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt | |

6 | ||

7 | helpMessage=""" | |

8 | ||

9 | DateTimeManager.py | |

10 | ================== | |

11 | ||

12 | Holds the class DateTimeManager that is a component time object copied | |

13 | from Bob Drach's cdtime within CDAT (Thanks Bob!). The reason for | |

14 | this duplication is that cdtime has dependencies on other software | |

15 | and is partly written in C. This version is entirely python and is | |

16 | therefore more portable. | |

17 | ||

18 | The class DateTimeManager has the following methods exposed to the user: | |

19 | ||

20 | add(n, units) - to add an interval to the current time object. | |

21 | sub(n, units) - to subtract an interval to the current time object. | |

22 | createList(s, e, i) - generate a list of times from s(tart) to e(nd) | |

23 | with i(nterval). | |

24 | printtime(format_string) - prints the time using typical python time formatting. | |

25 | getDaysInMonth(month, year) - returns the number of days in a given month. | |

26 | ||

27 | The createList(s, e, i) function is a wrapper around DateTimeManager.createList() at the | |

28 | module level. | |

29 | ||

30 | ||

31 | Usage: | |

32 | ====== | |

33 | ||

34 | To create a date-time instance for midday Christmas day 2003: | |

35 | ||

36 | mytime=DateTimeManager(2003, 12, 25, 12, 0, 0) | |

37 | ||

38 | To add 3 months to the instance: | |

39 | ||

40 | mytime.add(3, "months") | |

41 | ||

42 | To create a list of dates and times: | |

43 | ||

44 | mylist=createList("1999-01-01 00:00:00", "1999-01-22 12:00:00", (6, "hour")) | |

45 | ||

46 | ||

47 | """ | |

48 | ||

49 | # Import standard library modules | |

50 | import re, types, time | |

51 | ||

52 | def daysInMonth(month, year): | |

53 | """ | |

54 | Function wrapper around DateTimeManager.getDaysInMonth() method. | |

55 | """ | |

56 | dt=DateTimeManager() | |

57 | return dt.getDaysInMonth(month, year) | |

58 | ||

59 | ||

60 | def createList(start, end, interval=(6, "hour"), listtype="string", formatstring="%Y-%m-%d %H:%M:%S"): | |

61 | """ | |

62 | Function wrappper around DateTimeManager.createList() method. | |

63 | """ | |

64 | dt=DateTimeManager() | |

65 | return dt.createList(start, end, interval, listtype, formatstring) | |

66 | ||

67 | ||

68 | def getTimeBins(timelist): | |

69 | """ | |

70 | Function wrapper around DateTimeManager.getTimeBins() method. | |

71 | """ | |

72 | dt=DateTimeManager() | |

73 | return dt.getTimeBins(timelist) | |

74 | ||

75 | ||

76 | ||

77 | class DateTimeManager: | |

78 | """ | |

79 | Class to return lists of dates and times and allow adding and | |

80 | subtracting of time intervals from time objects. | |

81 | """ | |

82 | ||

83 | # Class level parameters (do not change) | |

84 | units={"year":"y ys yr yrs year years", | |

85 | "month":"mon mons mnth mnths month months", | |

86 | "day":"d ds dy dys day days", | |

87 | "hour":"h hs hr hrs hour hours", | |

88 | "minute":"min mins minute minutes", | |

89 | "second":"s sc scs sec secs scnd scnds second seconds"} | |

90 | positions=["year", "month", "day", "hour", "minute", "second"] | |

91 | max=[99999, 13, None, 24, 60, 60] # These are the secs in mins etc... | |

92 | min=[0, 1, 1, 0, 0, 0] | |

93 | ||

94 | ||

95 | def __init__(self, year=0, month=1, day=1, hour=0, minute=0, second=0): | |

96 | """ | |

97 | Method to set up the instance formats and basic objects. | |

98 | """ | |

99 | self.formats={"%Y":("%.4d","year"), "%y":("%.2d", "2dyear"), "%m":("%.2d","month"), "%d":("%.2d", "day"), | |

100 | "%H":("%.2d", "hour"), "%M":("%.2d", "minute"), "%S":("%.2d", "second")} | |

101 | self.datetime=[year, month, day, hour, minute, second] | |

102 | for i in range(0,6): | |

103 | if type(self.datetime[i])!=types.IntType: | |

104 | raise "Time components should be an integer: %s" % self.datetime[i] | |

105 | max=DateTimeManager.max | |

106 | max[2]=self.getDaysInMonth(month, year) | |

107 | if self.datetime[i]>=max[i]: | |

108 | raise "Time component '%s' must be less than limits: %s" % (self.datetime[i], str(max)) | |

109 | #print self.__repr__() | |

110 | ||

111 | ||

112 | ########################################## | |

113 | # | |

114 | # __getattr__() method | |

115 | # | |

116 | ########################################## | |

117 | def __getattr__(self, att): | |

118 | if att in DateTimeManager.positions: | |

119 | return self.datetime[DateTimeManager.positions.index(att)] | |

120 | elif att=="datetime": | |

121 | return self.__repr__() | |

122 | return "Attribute not found: %s" % att | |

123 | ||

124 | ||

125 | ########################################## | |

126 | # | |

127 | # __repr__() method | |

128 | # | |

129 | ########################################## | |

130 | def __repr__(self): | |

131 | return "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % tuple(self.datetime) | |

132 | ||

133 | ||

134 | ########################################## | |

135 | # | |

136 | # __str__() method | |

137 | # | |

138 | ########################################## | |

139 | def __str__(self): | |

140 | return "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % tuple(self.datetime) | |

141 | ||

142 | ||

143 | ########################################## | |

144 | # | |

145 | # add() method | |

146 | # | |

147 | ########################################## | |

148 | def add(self, n, unit="hour"): | |

149 | self.datetime=self._add(n, unit, self.datetime) | |

150 | return self.__repr__() | |

151 | ||

152 | ||

153 | ########################################## | |

154 | # | |

155 | # _add() method | |

156 | # | |

157 | ########################################## | |

158 | def _add(self, n, unit="hour", itime=None): | |

159 | unit=unit.lower() | |

160 | if type(n)==types.TupleType: | |

161 | increment=n | |

162 | else: | |

163 | for i in DateTimeManager.units.keys(): | |

164 | if i.find(unit)>-1 or DateTimeManager.units[i].find(unit)>-1: | |

165 | unit=i | |

166 | unitindex=DateTimeManager.positions.index(unit) | |

167 | increment=[0,0,0,0,0,0] | |

168 | increment[unitindex]=n | |

169 | break | |

170 | itime=self._recalculate(increment, itime) | |

171 | return itime | |

172 | ||

173 | ||

174 | ########################################## | |

175 | # | |

176 | # _recalculate() method | |

177 | # | |

178 | ########################################## | |

179 | def _recalculate(self, increment, itime): | |

180 | max=DateTimeManager.max | |

181 | min=DateTimeManager.min | |

182 | for x in range(5,-1,-1): | |

183 | if increment[x]==0: | |

184 | continue | |

185 | else: | |

186 | if x==2: # Calc days in month | |

187 | max[x]=self.getDaysInMonth(itime[1], itime[0])+1 | |

188 | itime[x]=itime[x]+increment[x] | |

189 | if itime[x]>=max[x]: | |

190 | remainder=itime[x]%max[x] | |

191 | up_one=itime[x]/max[x] | |

192 | if remainder==0: | |

193 | itime[x]=min[x] | |

194 | else: | |

195 | itime[x]=remainder | |

196 | itime[x] | |

197 | increment[x-1]=increment[x-1]+up_one | |

198 | #print itime | |

199 | return itime | |

200 | ||

201 | ||

202 | ########################################## | |

203 | # | |

204 | # sub() method | |

205 | # | |

206 | ########################################## | |

207 | def sub(self, n, unit="hour"): | |

208 | pass | |

209 | ||

210 | ||

211 | ########################################## | |

212 | # | |

213 | # createList() method | |

214 | # | |

215 | ########################################## | |

216 | def createList(self, start, end, interval=(6, "hour"), listtype="string", formatstring="%Y-%m-%d %H:%M:%S"): | |

217 | if type(start)==types.StringType: | |

218 | timepatt=("(\d{4})-(\d{1,2})-(\d{1,2})[ T](\d{1,2}):(\d{1,2}):(\d{1,2})") | |

219 | startmatch=re.match(timepatt, start) | |

220 | endmatch=re.match(timepatt, end) | |

221 | if startmatch: | |

222 | start=[] | |

223 | for i in startmatch.groups(): | |

224 | start.append(int(i)) | |

225 | if endmatch: | |

226 | end=[] | |

227 | for i in list(endmatch.groups()): | |

228 | end.append(int(i)) | |

229 | else: | |

230 | filler=[0,1,1,0,0,0] | |

231 | start=list(start)+filler[len(start):] | |

232 | end=list(end)+filler[len(end):] | |

233 | if type(start[0])!=type(1): | |

234 | startlist=[] | |

235 | endlist=[] | |

236 | for i in range(6): | |

237 | startlist.append(int(start[i])) | |

238 | endlist.append(int(end[i])) | |

239 | start=startlist | |

240 | end=endlist | |

241 | ||

242 | now=start | |

243 | rtlist=[] | |

244 | end[-1]=end[-1]+1 # add one second to end so it catches it in while loop | |

245 | while now<end: | |

246 | #print "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % tuple(now), "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % tuple(end) | |

247 | if listtype=="string": | |

248 | rtlist.append(self.formatTime(formatstring, tuple(now))) | |

249 | else: | |

250 | rtlist.append(tuple(now)) | |

251 | now=self._add(interval[0], interval[1], now) | |

252 | return rtlist | |

253 | ||

254 | ||

255 | ########################################## | |

256 | # | |

257 | # getDaysInMonth() method | |

258 | # | |

259 | ########################################## | |

260 | def getDaysInMonth(self, month, year): | |

261 | if month==2 and year%4==0: | |

262 | return 29 | |

263 | else: | |

264 | monthmap=(None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) | |

265 | return monthmap[month] | |

266 | ||

267 | ||

268 | ########################################## | |

269 | # | |

270 | # printtime() method | |

271 | # | |

272 | ########################################## | |

273 | def printtime(self, formatstring="%Y-%m-%d %H:%M:%S", itime=None): | |

274 | ftime=self.formatTime(formatstring, itime) | |

275 | print ftime | |

276 | return | |

277 | ||

278 | ||

279 | ########################################## | |

280 | # | |

281 | # formatTime() method | |

282 | # | |

283 | ########################################## | |

284 | def formatTime(self, formatstring="%Y-%m-%d %H:%M:%S", itime=None): | |

285 | if itime==None: itime=self.datetime | |

286 | #itimeDict={} | |

287 | #count=0 | |

288 | #for k in ("year", "month", "day", "hour", "minute", "second"): | |

289 | # itimeDict[k]=itime[count] | |

290 | # count=count+1 | |

291 | #checkCount=0 | |

292 | formatstring=time.strftime(formatstring, tuple(list((itime))+[0,1,0])) | |

293 | #while formatstring.find("%")>-1: # Keep in while loop just in case more than one occurrence of a field required | |

294 | # checkCount=checkCount+1 | |

295 | # for f in self.formats.keys(): | |

296 | # (formatter, item)=self.formats[f] | |

297 | # if type(item)==types.StringType: | |

298 | # replacer=formatter % itimeDict[item] | |

299 | # else: | |

300 | # replacer=formatter % (apply(item, (itime,))) | |

301 | # formatstring=formatstring.replace(f, replacer) | |

302 | # if checkCount>10: | |

303 | # raise "Cannot interpret remaining characters in: '%s'" % (formatstring) | |

304 | return formatstring | |

305 | ||

306 | def getTimeBins(self, timelist): | |

307 | """ | |

308 | Method to collect all available values of year, month, day etc into individual | |

309 | lists for populating selection boxes. | |

310 | """ | |

311 | # check type of input list | |

312 | if type(timelist[0])!=tuple: | |

313 | raise "Timelist items must be tuples." | |

314 | # Create an empty list | |

315 | nitems=len(timelist[0]) | |

316 | binlist=[] | |

317 | for i in range(nitems): | |

318 | binlist.append([]) | |

319 | ||

320 | # Populate the return list | |

321 | for t in timelist: | |

322 | for i in range(nitems): | |

323 | if t[i] not in binlist[i]: binlist[i].append(t[i]) | |

324 | ||

325 | # Make sure they are sorted | |

326 | for i in range(nitems): | |

327 | binlist[i].sort() | |

328 | ||

329 | return binlist | |

330 | ||

331 | ||

332 | ############################################## | |

333 | # | |

334 | # class UMTime | |

335 | # | |

336 | ############################################## | |

337 | class UMTime(DateTimeManager): | |

338 | ||

339 | ########################################## | |

340 | # | |

341 | # __init__() method | |

342 | # | |

343 | ########################################## | |

344 | def __init__(self, year=0, month=1, day=1, hour=0, minute=0, second=0): | |

345 | DateTimeManager.__init__(self, year, month, day, hour, minute, second) | |

346 | self.formats["%umyear"]=("%.4d_%s", self.getUMYear) | |

347 | ||

348 | ||

349 | ########################################## | |

350 | # | |

351 | # getUMYear() method | |

352 | # | |

353 | ########################################## | |

354 | def getUMYear(self, itime): | |

355 | umyear=itime[0]+1800 | |

356 | return (umyear, "holiday") | |

357 | ||

358 | ||

359 | ||

360 | ||

361 | ||

362 | ||

363 | ||

364 |

**Note:**See TracBrowser for help on using the repository browser.