Package netcdftime :: Module netcdftime
[hide private]
[frames] | no frames]

Source Code for Module netcdftime.netcdftime

  1  """ 
  2  Performs conversions of netCDF time coordinate data to/from datetime objects. 
  3  """ 
  4  import math, numpy 
  5  from datetime import datetime as real_datetime 
  6  from strptime import strptime 
  7  from strftime import strftime 
  8   
  9  _units = ['days','hours','minutes','seconds','day','hour','minute','second'] 
 10  _calendars = ['standard','gregorian','proleptic_gregorian','noleap','julian','all_leap','365_day','366_day','360_day'] 
 11   
 12  __version__ = '0.5' 
 13   
14 -class datetime:
15 """ 16 Phony datetime object which mimics the python datetime object, 17 but allows for dates that don't exist in the proleptic gregorian calendar. 18 Doesn't do timedelta operations, doesn't overload + and -. 19 20 Has strftime, timetuple and __repr__ methods. The format 21 of the string produced by __repr__ is controlled by self.format 22 (default %Y-%m-%d %H:%M:%S). 23 24 Instance variables are year,month,day,hour,minute,second,dayofwk,dayofyr 25 and format. 26 """
27 - def __init__(self,year,month,day,hour=0,minute=0,second=0,dayofwk=-1,dayofyr=1):
28 """dayofyr set to 1 by default - otherwise time.strftime will complain""" 29 self.year=year 30 self.month=month 31 self.day=day 32 self.hour=hour 33 self.minute=minute 34 self.dayofwk=dayofwk 35 self.dayofyr=dayofyr 36 self.second=second 37 self.format='%Y-%m-%d %H:%M:%S'
38 - def strftime(self,format=None):
39 if format is None: 40 format = self.format 41 return strftime(self,format)
42 - def timetuple(self):
43 return (self.year,self.month,self.day,self.hour,self.minute,self.second,self.dayofwk,self.dayofyr,-1)
44 - def __repr__(self):
45 return self.strftime(self.format)
46
47 -def JulianDayFromDate(date,calendar='standard'):
48 49 """ 50 51 creates a Julian Day from a 'datetime-like' object. Returns the fractional 52 Julian Day (resolution 1 second). 53 54 if calendar='standard' or 'gregorian' (default), Julian day follows Julian 55 Calendar on and before 1582-10-5, Gregorian calendar after 1582-10-15. 56 57 if calendar='proleptic_gregorian', Julian Day follows gregorian calendar. 58 59 if calendar='julian', Julian Day follows julian calendar. 60 61 Algorithm: 62 63 Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell, 64 Virginia. p. 63 65 66 """ 67 68 # based on redate.py by David Finlayson. 69 70 year=date.year; month=date.month; day=date.day 71 hour=date.hour; minute=date.minute; second=date.second 72 # Convert time to fractions of a day 73 day = day + hour/24.0 + minute/1440.0 + second/86400.0 74 75 # Start Meeus algorithm (variables are in his notation) 76 if (month < 3): 77 month = month + 12 78 year = year - 1 79 80 A = int(year/100) 81 82 jd = int(365.25 * (year + 4716)) + int(30.6001 * (month + 1)) + \ 83 day - 1524.5 84 85 # optionally adjust the jd for the switch from 86 # the Julian to Gregorian Calendar 87 # here assumed to have occurred the day after 1582 October 4 88 if calendar in ['standard','gregorian']: 89 if jd >= 2299170.5: 90 # 1582 October 15 (Gregorian Calendar) 91 B = 2 - A + int(A/4) 92 elif jd < 2299160.5: 93 # 1582 October 5 (Julian Calendar) 94 B = 0 95 else: 96 raise ValueError, 'impossible date (falls in gap between end of Julian calendar and beginning of Gregorian calendar' 97 elif calendar == 'proleptic_gregorian': 98 B = 2 - A + int(A/4) 99 elif calendar == 'julian': 100 B = 0 101 else: 102 raise ValueError, 'unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar 103 104 # adjust for Julian calendar if necessary 105 jd = jd + B 106 107 return jd
108
109 -def _NoLeapDayFromDate(date):
110 111 """ 112 113 creates a Julian Day for a calendar with no leap years from a datetime 114 instance. Returns the fractional Julian Day (resolution 1 second). 115 116 """ 117 118 year=date.year; month=date.month; day=date.day 119 hour=date.hour; minute=date.minute; second=date.second 120 # Convert time to fractions of a day 121 day = day + hour/24.0 + minute/1440.0 + second/86400.0 122 123 # Start Meeus algorithm (variables are in his notation) 124 if (month < 3): 125 month = month + 12 126 year = year - 1 127 128 jd = int(365. * (year + 4716)) + int(30.6001 * (month + 1)) + \ 129 day - 1524.5 130 131 return jd
132
133 -def _AllLeapFromDate(date):
134 135 """ 136 137 creates a Julian Day for a calendar where all years have 366 days from 138 a 'datetime-like' object. 139 Returns the fractional Julian Day (resolution 1 second). 140 141 """ 142 143 year=date.year; month=date.month; day=date.day 144 hour=date.hour; minute=date.minute; second=date.second 145 # Convert time to fractions of a day 146 day = day + hour/24.0 + minute/1440.0 + second/86400.0 147 148 # Start Meeus algorithm (variables are in his notation) 149 if (month < 3): 150 month = month + 12 151 year = year - 1 152 153 jd = int(366. * (year + 4716)) + int(30.6001 * (month + 1)) + \ 154 day - 1524.5 155 156 return jd
157
158 -def _360DayFromDate(date):
159 160 """ 161 162 creates a Julian Day for a calendar where all months have 30 daysfrom 163 a 'datetime-like' object. 164 Returns the fractional Julian Day (resolution 1 second). 165 166 """ 167 168 year=date.year; month=date.month; day=date.day 169 hour=date.hour; minute=date.minute; second=date.second 170 # Convert time to fractions of a day 171 day = day + hour/24.0 + minute/1440.0 + second/86400.0 172 173 jd = int(360. * (year + 4716)) + int(30. * (month - 1)) + day 174 175 return jd
176
177 -def DateFromJulianDay(JD,calendar='standard'):
178 """ 179 180 returns a 'datetime-like' object given Julian Day. Julian Day is a 181 fractional day with a resolution of 1 second. 182 183 if calendar='standard' or 'gregorian' (default), Julian day follows Julian 184 Calendar on and before 1582-10-5, Gregorian calendar after 1582-10-15. 185 186 if calendar='proleptic_gregorian', Julian Day follows gregorian calendar. 187 188 if calendar='julian', Julian Day follows julian calendar. 189 190 The datetime object is a 'real' datetime object if the date falls in 191 the Gregorian calendar (i.e. calendar='proleptic_gregorian', or 192 calendar = 'standard'/'gregorian' and the date is after 1582-10-15). 193 Otherwise, it's a 'phony' datetime object which is actually an instance 194 of netcdftime.datetime. 195 196 197 Algorithm: 198 199 Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell, 200 Virginia. p. 63 201 202 """ 203 204 # based on redate.py by David Finlayson. 205 206 if JD < 0: 207 raise ValueError, 'Julian Day must be positive' 208 209 dayofwk = int(math.fmod(int(JD + 1.5),7)) 210 (F, Z) = math.modf(JD + 0.5) 211 Z = int(Z) 212 if calendar in ['standard','gregorian']: 213 if JD < 2299160.5: 214 A = Z 215 else: 216 alpha = int((Z - 1867216.25)/36524.25) 217 A = Z + 1 + alpha - int(alpha/4) 218 219 elif calendar == 'proleptic_gregorian': 220 alpha = int((Z - 1867216.25)/36524.25) 221 A = Z + 1 + alpha - int(alpha/4) 222 elif calendar == 'julian': 223 A = Z 224 else: 225 raise ValueError, 'unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar 226 227 B = A + 1524 228 C = int((B - 122.1)/365.25) 229 D = int(365.25 * C) 230 E = int((B - D)/30.6001) 231 232 # Convert to date 233 day = B - D - int(30.6001 * E) + F 234 nday = B-D-123 235 if nday <= 305: 236 dayofyr = nday+60 237 else: 238 dayofyr = nday-305 239 if E < 14: 240 month = E - 1 241 else: 242 month = E - 13 243 244 if month > 2: 245 year = C - 4716 246 else: 247 year = C - 4715 248 249 # a leap year? 250 leap = 0 251 if year % 4 == 0: 252 leap = 1 253 if calendar == 'proleptic_gregorian' or \ 254 (calendar in ['standard','gregorian'] and JD >= 2299160.5): 255 if year % 100 == 0 and year % 400 != 0: 256 print year % 100, year % 400 257 leap = 0 258 if leap and month > 2: 259 dayofyr = dayofyr + leap 260 261 # Convert fractions of a day to time 262 (dfrac, days) = math.modf(day/1.0) 263 (hfrac, hours) = math.modf(dfrac * 24.0) 264 (mfrac, minutes) = math.modf(hfrac * 60.0) 265 seconds = round(mfrac * 60.0) # seconds are rounded 266 267 if seconds > 59: 268 seconds = 0 269 minutes = minutes + 1 270 if minutes > 59: 271 minutes = 0 272 hours = hours + 1 273 if hours > 23: 274 hours = 0 275 days = days + 1 276 277 # return a 'real' datetime instance if calendar is gregorian. 278 if calendar == 'proleptic_gregorian' or \ 279 (calendar in ['standard','gregorian'] and JD >= 2299160.5): 280 return real_datetime(year,month,int(days),int(hours),int(minutes),int(seconds)) 281 else: 282 # or else, return a 'datetime-like' instance. 283 return datetime(year,month,int(days),int(hours),int(minutes),int(seconds),dayofwk,dayofyr)
284
285 -def _DateFromNoLeapDay(JD):
286 """ 287 288 returns a 'datetime-like' object given Julian Day for a calendar with no leap 289 days. Julian Day is a fractional day with a resolution of 1 second. 290 291 """ 292 293 # based on redate.py by David Finlayson. 294 295 if JD < 0: 296 raise ValueError, 'Julian Day must be positive' 297 298 dayofwk = int(math.fmod(int(JD + 1.5),7)) 299 (F, Z) = math.modf(JD + 0.5) 300 Z = int(Z) 301 A = Z 302 B = A + 1524 303 C = int((B - 122.1)/365.) 304 D = int(365. * C) 305 E = int((B - D)/30.6001) 306 307 # Convert to date 308 day = B - D - int(30.6001 * E) + F 309 nday = B-D-123 310 if nday <= 305: 311 dayofyr = nday+60 312 else: 313 dayofyr = nday-305 314 if E < 14: 315 month = E - 1 316 else: 317 month = E - 13 318 319 if month > 2: 320 year = C - 4716 321 else: 322 year = C - 4715 323 324 # Convert fractions of a day to time 325 (dfrac, days) = math.modf(day/1.0) 326 (hfrac, hours) = math.modf(dfrac * 24.0) 327 (mfrac, minutes) = math.modf(hfrac * 60.0) 328 seconds = round(mfrac * 60.0) # seconds are rounded 329 330 if seconds > 59: 331 seconds = 0 332 minutes = minutes + 1 333 if minutes > 59: 334 minutes = 0 335 hours = hours + 1 336 if hours > 23: 337 hours = 0 338 days = days + 1 339 340 return datetime(year,month,int(days),int(hours),int(minutes),int(seconds), dayofwk, dayofyr)
341
342 -def _DateFromAllLeap(JD):
343 """ 344 345 returns a 'datetime-like' object given Julian Day for a calendar where all 346 years have 366 days. 347 Julian Day is a fractional day with a resolution of 1 second. 348 349 """ 350 351 # based on redate.py by David Finlayson. 352 353 if JD < 0: 354 raise ValueError, 'Julian Day must be positive' 355 356 dayofwk = int(math.fmod(int(JD + 1.5),7)) 357 (F, Z) = math.modf(JD + 0.5) 358 Z = int(Z) 359 A = Z 360 B = A + 1524 361 C = int((B - 122.1)/366.) 362 D = int(366. * C) 363 E = int((B - D)/30.6001) 364 365 # Convert to date 366 day = B - D - int(30.6001 * E) + F 367 nday = B-D-123 368 if nday <= 305: 369 dayofyr = nday+60 370 else: 371 dayofyr = nday-305 372 if E < 14: 373 month = E - 1 374 else: 375 month = E - 13 376 if month > 2: 377 dayofyr = dayofyr+1 378 379 if month > 2: 380 year = C - 4716 381 else: 382 year = C - 4715 383 384 # Convert fractions of a day to time 385 (dfrac, days) = math.modf(day/1.0) 386 (hfrac, hours) = math.modf(dfrac * 24.0) 387 (mfrac, minutes) = math.modf(hfrac * 60.0) 388 seconds = round(mfrac * 60.0) # seconds are rounded 389 390 if seconds > 59: 391 seconds = 0 392 minutes = minutes + 1 393 if minutes > 59: 394 minutes = 0 395 hours = hours + 1 396 if hours > 23: 397 hours = 0 398 days = days + 1 399 400 return datetime(year,month,int(days),int(hours),int(minutes),int(seconds), dayofwk, dayofyr)
401
402 -def _DateFrom360Day(JD):
403 """ 404 405 returns a 'datetime-like' object given Julian Day for a calendar where all 406 months have 30 days. 407 Julian Day is a fractional day with a resolution of 1 second. 408 409 """ 410 411 if JD < 0: 412 raise ValueError, 'Julian Day must be positive' 413 414 #jd = int(360. * (year + 4716)) + int(30. * (month - 1)) + day 415 (F, Z) = math.modf(JD) 416 year = int((Z-0.5)/360.) - 4716 417 dayofyr = JD - (year+4716)*360 418 month = int((dayofyr-0.5)/30)+1 419 day = dayofyr - (month-1)*30 + F 420 421 # Convert fractions of a day to time 422 (dfrac, days) = math.modf(day/1.0) 423 (hfrac, hours) = math.modf(dfrac * 24.0) 424 (mfrac, minutes) = math.modf(hfrac * 60.0) 425 seconds = round(mfrac * 60.0) # seconds are rounded 426 427 if seconds > 59: 428 seconds = 0 429 minutes = minutes + 1 430 if minutes > 59: 431 minutes = 0 432 hours = hours + 1 433 if hours > 23: 434 hours = 0 435 days = days + 1 436 437 return datetime(year,month,int(days),int(hours),int(minutes),int(seconds),-1, int(dayofyr))
438
439 -def _dateparse(timestr,format='%Y-%m-%d %H:%M:%S'):
440 """parse a string of the form time-units since yyyy-mm-dd hh:mm:ss 441 return a tuple (units, datetimeinstance)""" 442 timestr_split = timestr.split() 443 units = timestr_split[0].lower() 444 if units not in _units: 445 raise ValueError,"units must be one of 'seconds', 'minutes', 'hours' or 'days' (or singular version of these), got '%s'" % units 446 if timestr_split[1].lower() != 'since': 447 raise ValueError,"no 'since' in unit_string" 448 # use strptime to parse the date string. 449 n = timestr.find('since')+6 450 year,month,day,hour,minute,second,daywk,dayyr,tz = strptime(timestr[n:],format) 451 if dayyr == -1: dayyr=1 # must have valid day of year for strftime to work 452 return units, datetime(year, month, day, hour, minute, second, daywk, dayyr)
453
454 -class utime:
455 """ 456 Performs conversions of netCDF time coordinate 457 data to/from datetime objects. 458 459 To initialize: C{t = utime(unit_string,format='%Y-%m-%d %H:%M:%S',calendar='standard')} 460 461 where 462 463 B{C{unit_string}} is a string of the form 464 C{'time-units since <format>'} defining the time units. 465 466 B{C{format}} is a string describing a reference time. This string is converted 467 to a year,month,day,hour,minute,second tuple by strptime. The default 468 format is C{'%Y-%m-%d %H:%M:%S'}. See the C{time.strptime} docstring for other 469 valid formats. 470 471 Valid time-units are days, hours, minutes and seconds (the singular forms 472 are also accepted). An example unit_string would be C{'hours 473 since 0001-01-01 00:00:00'}. 474 475 The B{C{calendar}} keyword describes the calendar used in the time calculations. 476 All the values currently defined in the U{CF metadata convention 477 <http://www.cgd.ucar.edu/cms/eaton/cf-metadata/CF-1.0.html#time>} are 478 accepted. The default is C{'standard'}, which corresponds to the mixed 479 Gregorian/Julian calendar used by the C{udunits library}. Valid calendars 480 are: 481 482 C{'gregorian'} or C{'standard'} (default): 483 484 Mixed Gregorian/Julian calendar as defined by udunits. 485 486 C{'proleptic_gregorian'}: 487 488 A Gregorian calendar extended to dates before 1582-10-15. That is, a year 489 is a leap year if either (i) it is divisible by 4 but not by 100 or (ii) 490 it is divisible by 400. 491 492 C{'noleap'} or C{'365_day'}: 493 494 Gregorian calendar without leap years, i.e., all years are 365 days long. 495 all_leap or 366_day Gregorian calendar with every year being a leap year, 496 i.e., all years are 366 days long. 497 498 C{'360_day'}: 499 500 All years are 360 days divided into 30 day months. 501 502 C{'julian'}: 503 504 Proleptic Julian calendar, extended to dates after 1582-10-5. A year is a 505 leap year if it is divisible by 4. 506 507 The C{L{num2date}} and C{L{date2num}} class methods can used to convert datetime 508 instances to/from the specified time units using the specified calendar. 509 510 The datetime instances returned by C{num2date} are 'real' python datetime 511 objects if the date falls in the Gregorian calendar (i.e. 512 C{calendar='proleptic_gregorian', 'standard'} or C{'gregorian'} and 513 the date is after 1582-10-15). Otherwise, they are 'phony' datetime 514 objects which are actually instances of C{L{netcdftime.datetime}}. This is 515 because the python datetime module cannot handle the weird dates in some 516 calendars (such as C{'360_day'} and C{'all_leap'}) which don't exist in any real 517 world calendar. 518 519 520 Example usage: 521 522 >>> from netcdftime import utime 523 >>> from datetime import datetime 524 >>> cdftime = utime('hours since 0001-01-01 00:00:00') 525 >>> date = datetime.now() 526 >>> print date 527 2006-03-17 16:04:02.561678 528 >>> 529 >>> t = cdftime.date2num(date) 530 >>> print t 531 17577328.0672 532 >>> 533 >>> date = cdftime.num2date(t) 534 >>> print date 535 2006-03-17 16:04:02 536 >>> 537 538 The resolution of the transformation operation is 1 second. 539 540 Warning: Dates between 1582-10-5 and 1582-10-15 do not exist in the 541 C{'standard'} or C{'gregorian'} calendars. An exception will be raised if you pass 542 a 'datetime-like' object in that range to the C{L{date2num}} class method. 543 544 Words of Wisdom from the British MetOffice concerning reference dates 545 U{http://www.metoffice.com/research/hadleycentre/models/GDT/ch26.html}: 546 547 "udunits implements the mixed Gregorian/Julian calendar system, as 548 followed in England, in which dates prior to 1582-10-15 are assumed to use 549 the Julian calendar. Other software cannot be relied upon to handle the 550 change of calendar in the same way, so for robustness it is recommended 551 that the reference date be later than 1582. If earlier dates must be used, 552 it should be noted that udunits treats 0 AD as identical to 1 AD." 553 554 @ivar origin: datetime instance defining the origin of the netCDF time variable. 555 @ivar calendar: the calendar used (as specified by the C{calendar} keyword). 556 @ivar unit_string: a string defining the the netCDF time variable. 557 @ivar units: the units part of C{unit_string} (i.e. 'days', 'hours', 'seconds'). 558 """
559 - def __init__(self,unit_string,format='%Y-%m-%d %H:%M:%S',calendar='standard'):
560 """ 561 @param unit_string: a string of the form 562 C{'time-units since <format>'} defining the time units. 563 564 @keyword format: a string describing a reference time. This string is converted 565 to a year,month,day,hour,minute,second tuple by strptime. The default 566 format is C{'%Y-%m-%d %H:%M:%S'}. See the C{time.strptime} docstring for other 567 valid formats. 568 Valid time-units are days, hours, minutes and seconds (the singular forms 569 are also accepted). An example unit_string would be C{'hours 570 since 0001-01-01 00:00:00'}. 571 572 @keyword calendar: describes the calendar used in the time calculations. 573 All the values currently defined in the U{CF metadata convention 574 <http://www.cgd.ucar.edu/cms/eaton/cf-metadata/CF-1.0.html#time>} are 575 accepted. The default is C{'standard'}, which corresponds to the mixed 576 Gregorian/Julian calendar used by the C{udunits library}. Valid calendars 577 are: 578 - C{'gregorian'} or C{'standard'} (default): 579 Mixed Gregorian/Julian calendar as defined by udunits. 580 - C{'proleptic_gregorian'}: 581 A Gregorian calendar extended to dates before 1582-10-15. That is, a year 582 is a leap year if either (i) it is divisible by 4 but not by 100 or (ii) 583 it is divisible by 400. 584 - C{'noleap'} or C{'365_day'}: 585 Gregorian calendar without leap years, i.e., all years are 365 days long. 586 all_leap or 366_day Gregorian calendar with every year being a leap year, 587 i.e., all years are 366 days long. 588 -C{'360_day'}: 589 All years are 360 days divided into 30 day months. 590 -C{'julian'}: 591 Proleptic Julian calendar, extended to dates after 1582-10-5. A year is a 592 leap year if it is divisible by 4. 593 594 @returns: A class instance which may be used for converting times from netCDF 595 units to datetime objects. 596 """ 597 if calendar in _calendars: 598 self.calendar = calendar 599 else: 600 raise ValueError, "calendar must be one of %s, got '%s'" % (str(_calendars),calendar) 601 units, self.origin = _dateparse(unit_string,format=format) 602 self.units = units 603 self.unit_string = unit_string 604 if self.calendar in ['noleap','365_day'] and self.origin.month == 2 and self.origin.day == 29: 605 raise ValueError, 'cannot specify a leap day as the reference time with the noleap calendar' 606 if self.calendar == '360_day' and self.origin.day > 30: 607 raise ValueError, 'there are only 30 days in every month with the 360_day calendar' 608 if self.calendar in ['noleap','365_day']: 609 self._jd0 = _NoLeapDayFromDate(self.origin) 610 elif self.calendar in ['all_leap','366_day']: 611 self._jd0 = _AllLeapFromDate(self.origin) 612 elif self.calendar == '360_day': 613 self._jd0 = _360DayFromDate(self.origin) 614 else: 615 self._jd0 = JulianDayFromDate(self.origin,calendar=self.calendar)
616
617 - def date2num(self,date):
618 """ 619 Returns C{time_value} in units described by L{unit_string}, using 620 the specified L{calendar}, given a 'datetime-like' object. 621 622 Resolution is 1 second. 623 624 If C{calendar = 'standard'} or C{'gregorian'} (indicating 625 that the mixed Julian/Gregorian calendar is to be used), an 626 exception will be raised if the 'datetime-like' object describes 627 a date between 1582-10-5 and 1582-10-15. 628 629 Works for scalars, sequences and numpy arrays. 630 Returns a scalar if input is a scalar, else returns a numpy array. 631 """ 632 isscalar = False 633 try: 634 date[0] 635 except: 636 isscalar = True 637 if not isscalar: 638 date = numpy.array(date) 639 shape = date.shape 640 if self.calendar in ['julian','standard','gregorian','proleptic_gregorian']: 641 if isscalar: 642 jdelta = JulianDayFromDate(date,self.calendar)-self._jd0 643 else: 644 jdelta = [JulianDayFromDate(d,self.calendar)-self._jd0 for d in date.flat] 645 elif self.calendar in ['noleap','365_day']: 646 if date.month == 2 and date.day == 29: 647 raise ValueError, 'there is no leap day in the noleap calendar' 648 if isscalar: 649 jdelta = _NoLeapDayFromDate(date) - self._jd0 650 else: 651 jdelta = [_NoLeapDayFromDate(d)-self._jd0 for d in date.flat] 652 elif self.calendar in ['all_leap','366_day']: 653 if isscalar: 654 jdelta = _AllLeapFromDate(date) - self._jd0 655 else: 656 jdelta = [_AllLeapFromDate(d)-self._jd0 for d in date.flat] 657 elif self.calendar == '360_day': 658 if self.calendar == '360_day' and date.day > 30: 659 raise ValueError, 'there are only 30 days in every month with the 360_day calendar' 660 if isscalar: 661 jdelta = _360DayFromDate(date) - self._jd0 662 else: 663 jdelta = [_360DayFromDate(d)-self._jd0 for d in date.flat] 664 if not isscalar: 665 jdelta = numpy.array(jdelta) 666 if self.units in ['second','seconds']: 667 jdelta = jdelta*86400. 668 elif self.units in ['minute','minutes']: 669 jdelta = jdelta*1440. 670 elif self.units in ['hours','hours']: 671 jdelta = jdelta*24. 672 if isscalar: 673 return jdelta 674 else: 675 return numpy.reshape(jdelta,shape)
676
677 - def num2date(self,time_value):
678 """ 679 Return a 'datetime-like' object given a C{time_value} in units 680 described by L{unit_string}, using L{calendar}. 681 682 Resolution is 1 second. 683 684 Works for scalars, sequences and numpy arrays. 685 Returns a scalar if input is a scalar, else returns a numpy array. 686 687 The datetime instances returned by C{num2date} are 'real' python datetime 688 objects if the date falls in the Gregorian calendar (i.e. 689 C{calendar='proleptic_gregorian'}, or C{calendar = 'standard'/'gregorian'} and 690 the date is after 1582-10-15). Otherwise, they are 'phony' datetime 691 objects which are actually instances of netcdftime.datetime. This is 692 because the python datetime module cannot handle the weird dates in some 693 calendars (such as C{'360_day'} and C{'all_leap'}) which don't exist in any real 694 world calendar. 695 """ 696 isscalar = False 697 try: 698 time_value[0] 699 except: 700 isscalar = True 701 if not isscalar: 702 time_value = numpy.array(time_value) 703 shape = time_value.shape 704 if self.units in ['second','seconds']: 705 jdelta = time_value/86400. 706 elif self.units in ['minute','minutes']: 707 jdelta = time_value/1440. 708 elif self.units in ['hours','hours']: 709 jdelta = time_value/24. 710 elif self.units in ['day','days']: 711 jdelta = time_value 712 jd = self._jd0 + jdelta 713 if self.calendar in ['julian','standard','gregorian','proleptic_gregorian']: 714 if not isscalar: 715 date = [DateFromJulianDay(j,self.calendar) for j in jd.flat] 716 else: 717 date = DateFromJulianDay(jd,self.calendar) 718 elif self.calendar in ['noleap','365_day']: 719 if not isscalar: 720 date = [_DateFromNoLeapDay(j) for j in jd.flat] 721 else: 722 date = _DateFromNoLeapDay(jd) 723 elif self.calendar in ['all_leap','366_day']: 724 if not isscalar: 725 date = [_DateFromAllLeap(j) for j in jd.flat] 726 else: 727 date = _DateFromAllLeap(jd) 728 elif self.calendar == '360_day': 729 if not isscalar: 730 date = [_DateFrom360Day(j) for j in jd.flat] 731 else: 732 date = _DateFrom360Day(jd) 733 if isscalar: 734 return date 735 else: 736 return numpy.reshape(numpy.array(date),shape)
737