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