def datetime( year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, calendar='proleptic_gregorian'): """ Retrieves a datetime-like object with the requested calendar. Calendar types other than proleptic_gregorian require the netcdftime module to be installed. Parameters ---------- year : int, month : int, day : int, hour : int, optional minute : int, optional second : int, optional microsecond : int, optional tzinfo : datetime.tzinfo, optional A timezone informaton class, such as from pytz. Can only be used with 'proleptic_gregorian' calendar, as netcdftime does not support timezones. calendar : string, optional Should be one of 'proleptic_gregorian', 'no_leap', '365_day', 'all_leap', '366_day', '360_day', 'julian', or 'gregorian'. Default is 'proleptic_gregorian', which returns a normal Python datetime. Other options require the netcdftime module to be installed. Returns ------- datetime : datetime-like The requested datetime. May be a Python datetime, or one of the datetime-like types in netcdftime. """ kwargs = { 'year': year, 'month': month, 'day': day, 'hour': hour, 'minute': minute, 'second': second, 'microsecond': microsecond } if calendar.lower() == 'proleptic_gregorian': return real_datetime(tzinfo=tzinfo, **kwargs) elif tzinfo is not None: raise ValueError('netcdftime does not support timezone-aware datetimes') elif nt is None: raise DependencyError( "Calendars other than 'proleptic_gregorian' require the netcdftime " "package, which is not installed.") elif calendar.lower() in ('all_leap', '366_day'): return nt.DatetimeAllLeap(**kwargs) elif calendar.lower() in ('no_leap', 'noleap', '365_day'): return nt.DatetimeNoLeap(**kwargs) elif calendar.lower() == '360_day': return nt.Datetime360Day(**kwargs) elif calendar.lower() == 'julian': return nt.DatetimeJulian(**kwargs) elif calendar.lower() == 'gregorian': return nt.DatetimeGregorian(**kwargs)
def parse_date(raw_date): """Get the date in correct format using dateutil.parser. Note that if no month or day can be found in the raw date string, they will be set to 1 (e.g., "Mar 1999" -> "1999-03-01"). If the string cannot be parsed, return the string. """ if not raw_date: return raw_date if not isinstance(raw_date, str): raw_date = str(raw_date) try: DEFAULT_DATE = real_datetime(1, 1, 1) parsed_date = dparser.parse(raw_date, default=DEFAULT_DATE) date_published = parsed_date.date().isoformat() except ValueError: date_published = raw_date return date_published
def closest_date(date, date_from, date_to): """ Adjusts year so that the date is closest to the given range. Transactions dates in a statement usually contain only day and month. Statement dates range have a year though. Merge them all together to get a full transaction date. """ # If the date is within given range, we're done. if date_from <= date <= date_to: return date dates = [real_datetime(year, date.month, date.day) for year in xrange(date_from.year, date_to.year+1)] # Ideally, pick the date within given range. for d in dates: if date_from <= d <= date_to: return d # Otherwise, return the most recent date in the past. return min(dates, key=lambda d: abs(d-date_from))
def setUp(self): from datetime import datetime as real_datetime self.hour_before = real_datetime(2013, 1, 1, 9, 30, 0, 0) self.minute_before = real_datetime(2013, 1, 1, 10, 29, 0, 0) self.now = real_datetime(2013, 1, 1, 10, 30, 0, 0)
def strptime(date_string, fmt): """A strptime(date string, format) that support dates before 1900.""" return real_datetime(*(time.strptime(date_string, fmt)[:6]))
def strptime(date_string, fmt): return real_datetime(*(time.strptime(date_string, fmt)[:6]))
def DateFromJulianDate(JD, calendar='standard'): """ Algorithm: Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell, Virginia. p. 63 """ if JD < 0: raise ValueError('Julian Day must be positive') dayofwk = int(math.fmod(int(JD + 1.5), 7)) (F, Z) = math.modf(JD + 0.5) Z = int(Z) if calendar in ['standard', 'gregorian']: if JD < 2299160.5: A = Z else: alpha = int((Z - 1867216.25) / 36524.25) A = Z + 1 + alpha - int(alpha / 4) elif calendar == 'proleptic_gregorian': alpha = int((Z - 1867216.25) / 36524.25) A = Z + 1 + alpha - int(alpha / 4) elif calendar == 'julian': A = Z else: raise ValueError( 'unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar) B = A + 1524 C = int((B - 122.1) / 365.25) D = int(365.25 * C) E = int((B - D) / 30.6001) # Convert to date day = B - D - int(30.6001 * E) + F nday = B - D - 123 if nday <= 305: dayofyr = nday + 60 else: dayofyr = nday - 305 if E < 14: month = E - 1 else: month = E - 13 if month > 2: year = C - 4716 else: year = C - 4715 # a leap year? leap = 0 if year % 4 == 0: leap = 1 if calendar == 'proleptic_gregorian' or \ (calendar in ['standard','gregorian'] and JD >= 2299160.5): if year % 100 == 0 and year % 400 != 0: leap = 0 if leap and month > 2: dayofyr = dayofyr + leap # Convert fractions of a day to time (dfrac, days) = math.modf(day / 1.0) (hfrac, hours) = math.modf(dfrac * 24.0) (mfrac, minutes) = math.modf(hfrac * 60.0) seconds = round(mfrac * 60.0) # seconds are rounded if seconds > 59: seconds = 0 minutes = minutes + 1 if minutes > 59: minutes = 0 hours = hours + 1 if hours > 23: hours = 0 days = days + 1 daysinmonth = monthrange(year, month)[1] if days > daysinmonth: days = 1 month = month + 1 if month > 12: month = 1 year = year + 1 # return a 'real' datetime instance if calendar is gregorian. if calendar == 'proleptic_gregorian' or \ (calendar in ['standard','gregorian'] and JD >= 2299160.5): return real_datetime(year, month, int(days), int(hours), int(minutes), int(seconds)) else: # or else, return a 'datetime-like' instance. return datetime(year, month, int(days), int(hours), int(minutes), int(seconds), dayofwk, dayofyr)
def DateFromJulianDay(JD,calendar='standard'): """ returns a 'datetime-like' object given Julian Day. Julian Day is a fractional day with a resolution of 1 second. if calendar='standard' or 'gregorian' (default), Julian day follows Julian Calendar on and before 1582-10-5, Gregorian calendar after 1582-10-15. if calendar='proleptic_gregorian', Julian Day follows gregorian calendar. if calendar='julian', Julian Day follows julian calendar. The datetime object is a 'real' datetime object if the date falls in the Gregorian calendar (i.e. calendar='proleptic_gregorian', or calendar = 'standard'/'gregorian' and the date is after 1582-10-15). Otherwise, it's a 'phony' datetime object which is actually an instance of netcdftime.datetime. Algorithm: Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell, Virginia. p. 63 """ # based on redate.py by David Finlayson. if JD < 0: raise ValueError('Julian Day must be positive') dayofwk = int(math.fmod(int(JD + 1.5),7)) (F, Z) = math.modf(JD + 0.5) Z = int(Z) if calendar in ['standard','gregorian']: if JD < 2299160.5: A = Z else: # MC # alpha = int((Z - 1867216.25)/36524.25) # A = Z + 1 + alpha - int(alpha/4) alpha = int(((Z - 1867216.)-0.25)/36524.25) A = Z + 1 + alpha - int(0.25*alpha) elif calendar == 'proleptic_gregorian': # MC # alpha = int((Z - 1867216.25)/36524.25) # A = Z + 1 + alpha - int(alpha/4) alpha = int(((Z - 1867216.)-0.25)/36524.25) A = Z + 1 + alpha - int(0.25*alpha) elif calendar == 'julian': A = Z else: raise ValueError('unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar) B = A + 1524 # MC # C = int((B - 122.1)/365.25) # D = int(365.25 * C) C = int(6680.+((B-2439870.)-122.1)/365.25) D = 365*C + int(0.25 * C) E = int((B - D)/30.6001) # Convert to date day = B - D - int(30.6001 * E) + F nday = B-D-123 if nday <= 305: dayofyr = nday+60 else: dayofyr = nday-305 # MC # if E < 14: # month = E - 1 # else: # month = E - 13 # if month > 2: # year = C - 4716 # else: # year = C - 4715 month = E - 1 if month > 12: month -= 12 year = C - 4715 if month > 2: year -= 1 if year <= 0: year -= 1 # a leap year? leap = 0 if year % 4 == 0: leap = 1 if calendar == 'proleptic_gregorian' or \ (calendar in ['standard','gregorian'] and JD >= 2299160.5): if year % 100 == 0 and year % 400 != 0: leap = 0 if leap and month > 2: dayofyr = dayofyr + leap # Convert fractions of a day to time (dfrac, days) = math.modf(day/1.0) (hfrac, hours) = math.modf(dfrac * 24.0) (mfrac, minutes) = math.modf(hfrac * 60.0) seconds = round(mfrac * 60.0) # seconds are rounded if seconds > 59: seconds = 0 minutes = minutes + 1 if minutes > 59: minutes = 0 hours = hours + 1 if hours > 23: hours = 0 days = days + 1 # if days exceeds number allowed in a month, flip to next month. # this fixes issue 75. daysinmonth = monthrange(year, month)[1] if days > daysinmonth: days = 1 month = month + 1 if month > 12: month = 1 year = year + 1 # return a 'real' datetime instance if calendar is gregorian. if calendar == 'proleptic_gregorian' or \ (calendar in ['standard','gregorian'] and JD >= 2299160.5): return real_datetime(year,month,int(days),int(hours),int(minutes),int(seconds)) else: # or else, return a 'datetime-like' instance. return datetime(year,month,int(days),int(hours),int(minutes),int(seconds),dayofwk,dayofyr)
def DateFromJulianDay(JD, calendar='standard'): """ returns a 'datetime-like' object given Julian Day. Julian Day is a fractional day with a resolution of approximately 0.1 seconds. if calendar='standard' or 'gregorian' (default), Julian day follows Julian Calendar on and before 1582-10-5, Gregorian calendar after 1582-10-15. if calendar='proleptic_gregorian', Julian Day follows gregorian calendar. if calendar='julian', Julian Day follows julian calendar. The datetime object is a 'real' datetime object if the date falls in the Gregorian calendar (i.e. calendar='proleptic_gregorian', or calendar = 'standard'/'gregorian' and the date is after 1582-10-15). Otherwise, it's a 'phony' datetime object which is actually an instance of netcdftime.datetime. Algorithm: Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell, Virginia. p. 63 """ # based on redate.py by David Finlayson. julian = np.array(JD, dtype=float) if np.min(julian) < 0: raise ValueError('Julian Day must be positive') dayofwk = np.atleast_1d(np.int32(np.fmod(np.int32(julian + 1.5), 7))) # get the day (Z) and the fraction of the day (F) # add 0.000005 which is 452 ms in case of jd being after # second 23:59:59 of a day we want to round to the next day see issue #75 Z = np.atleast_1d(np.int32(np.round(julian + 0.00005))) F = np.atleast_1d(julian + 0.5 - Z).astype(np.float64) if calendar in ['standard', 'gregorian']: # MC # alpha = int((Z - 1867216.25)/36524.25) # A = Z + 1 + alpha - int(alpha/4) alpha = np.int32(((Z - 1867216.) - 0.25) / 36524.25) A = Z + 1 + alpha - np.int32(0.25 * alpha) # check if dates before oct 5th 1582 are in the array ind_before = np.where(julian < 2299160.5)[0] if len(ind_before) > 0: A[ind_before] = Z[ind_before] elif calendar == 'proleptic_gregorian': # MC # alpha = int((Z - 1867216.25)/36524.25) # A = Z + 1 + alpha - int(alpha/4) alpha = np.int32(((Z - 1867216.) - 0.25) / 36524.25) A = Z + 1 + alpha - np.int32(0.25 * alpha) elif calendar == 'julian': A = Z else: raise ValueError( 'unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar) B = A + 1524 # MC # C = int((B - 122.1)/365.25) # D = int(365.25 * C) C = np.atleast_1d(np.int32(6680. + ((B - 2439870.) - 122.1) / 365.25)) D = np.atleast_1d(np.int32(365 * C + np.int32(0.25 * C))) E = np.atleast_1d(np.int32((B - D) / 30.6001)) # Convert to date day = np.clip(B - D - np.int64(30.6001 * E) + F, 1, None) nday = B - D - 123 dayofyr = nday - 305 ind_nday_before = np.where(nday <= 305)[0] if len(ind_nday_before) > 0: dayofyr[ind_nday_before] = nday[ind_nday_before] + 60 # MC # if E < 14: # month = E - 1 # else: # month = E - 13 # if month > 2: # year = C - 4716 # else: # year = C - 4715 month = E - 1 month[month > 12] = month[month > 12] - 12 year = C - 4715 year[month > 2] = year[month > 2] - 1 year[year <= 0] = year[year <= 0] - 1 # a leap year? leap = np.zeros(len(year),dtype=dayofyr.dtype) leap[year % 4 == 0] = 1 if calendar == 'proleptic_gregorian': leap[(year % 100 == 0) & (year % 400 != 0)] = 0 elif calendar in ['standard', 'gregorian']: leap[(year % 100 == 0) & (year % 400 != 0) & (julian < 2299160.5)] = 0 inc_idx = np.where((leap == 1) & (month > 2))[0] dayofyr[inc_idx] = dayofyr[inc_idx] + leap[inc_idx] eps = np.clip( (1e-12 * np.abs(Z)).astype(np.float64), np.float64(1e-12), None) hour = np.clip((F * 24. + eps).astype(np.int64), 0, 23) F -= hour / 24. minute = np.clip((F * 1440. + eps).astype(np.int64), 0, 59) second = np.clip((F - minute / 1440.) * 86400., 0, None) # microseconds may not be accurate. microsecond = (second % 1)*1.e6 # convert year, month, day, hour, minute, second to int32 year = year.astype(np.int32) month = month.astype(np.int32) day = day.astype(np.int32) hour = hour.astype(np.int32) minute = minute.astype(np.int32) second = second.astype(np.int32) microsecond = microsecond.astype(np.int32) # check if input was scalar and change return accordingly isscalar = False try: JD[0] except: isscalar = True # return a 'real' datetime instance if calendar is gregorian. if calendar in 'proleptic_gregorian' or \ (calendar in ['standard', 'gregorian'] and len(ind_before) == 0): if not isscalar: return np.array([real_datetime(*args) for args in zip(year, month, day, hour, minute, second, microsecond)]) else: return real_datetime(year[0], month[0], day[0], hour[0], minute[0], second[0], microsecond[0]) else: # or else, return a 'datetime-like' instance. if not isscalar: return np.array([datetime(*args) for args in zip(year, month, day, hour, minute, second, microsecond, dayofwk, dayofyr)]) else: return datetime(year[0], month[0], day[0], hour[0], minute[0], second[0], microsecond[0], dayofwk[0], dayofyr[0])
def _to_real_datetime(self): return real_datetime(self._year, self._month, self._day, self._hour, self._minute, self._second)
def DateFromJulianDay(JD, calendar='standard'): """ returns a 'datetime-like' object given Julian Day. Julian Day is a fractional day with a resolution of 1 second. if calendar='standard' or 'gregorian' (default), Julian day follows Julian Calendar on and before 1582-10-5, Gregorian calendar after 1582-10-15. if calendar='proleptic_gregorian', Julian Day follows gregorian calendar. if calendar='julian', Julian Day follows julian calendar. The datetime object is a 'real' datetime object if the date falls in the Gregorian calendar (i.e. calendar='proleptic_gregorian', or calendar = 'standard'/'gregorian' and the date is after 1582-10-15). Otherwise, it's a 'phony' datetime object which is actually an instance of netcdftime.datetime. Algorithm: Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell, Virginia. p. 63 """ # based on redate.py by David Finlayson. if JD < 0: raise ValueError('Julian Day must be positive') dayofwk = int(math.fmod(int(JD + 1.5), 7)) (F, Z) = math.modf(JD + 0.5) Z = int(Z) if calendar in ['standard', 'gregorian']: if JD < 2299160.5: A = Z else: # MC # alpha = int((Z - 1867216.25)/36524.25) # A = Z + 1 + alpha - int(alpha/4) alpha = int(((Z - 1867216.) - 0.25) / 36524.25) A = Z + 1 + alpha - int(0.25 * alpha) elif calendar == 'proleptic_gregorian': # MC # alpha = int((Z - 1867216.25)/36524.25) # A = Z + 1 + alpha - int(alpha/4) alpha = int(((Z - 1867216.) - 0.25) / 36524.25) A = Z + 1 + alpha - int(0.25 * alpha) elif calendar == 'julian': A = Z else: raise ValueError( 'unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar) B = A + 1524 # MC # C = int((B - 122.1)/365.25) # D = int(365.25 * C) C = int(6680. + ((B - 2439870.) - 122.1) / 365.25) D = 365 * C + int(0.25 * C) E = int((B - D) / 30.6001) # Convert to date day = B - D - int(30.6001 * E) + F nday = B - D - 123 if nday <= 305: dayofyr = nday + 60 else: dayofyr = nday - 305 # MC # if E < 14: # month = E - 1 # else: # month = E - 13 # if month > 2: # year = C - 4716 # else: # year = C - 4715 month = E - 1 if month > 12: month -= 12 year = C - 4715 if month > 2: year -= 1 if year <= 0: year -= 1 # a leap year? leap = 0 if year % 4 == 0: leap = 1 if calendar == 'proleptic_gregorian' or \ (calendar in ['standard','gregorian'] and JD >= 2299160.5): if year % 100 == 0 and year % 400 != 0: leap = 0 if leap and month > 2: dayofyr = dayofyr + leap # Convert fractions of a day to time (dfrac, days) = math.modf(day / 1.0) (hfrac, hours) = math.modf(dfrac * 24.0) (mfrac, minutes) = math.modf(hfrac * 60.0) seconds = round(mfrac * 60.0) # seconds are rounded if seconds > 59: seconds = 0 minutes = minutes + 1 if minutes > 59: minutes = 0 hours = hours + 1 if hours > 23: hours = 0 days = days + 1 # if days exceeds number allowed in a month, flip to next month. # this fixes issue 75. daysinmonth = monthrange(year, month)[1] if days > daysinmonth: days = 1 month = month + 1 if month > 12: month = 1 year = year + 1 # return a 'real' datetime instance if calendar is gregorian. if calendar == 'proleptic_gregorian' or \ (calendar in ['standard','gregorian'] and JD >= 2299160.5): return real_datetime(year, month, int(days), int(hours), int(minutes), int(seconds)) else: # or else, return a 'datetime-like' instance. return datetime(year, month, int(days), int(hours), int(minutes), int(seconds), dayofwk, dayofyr)
def DateFromJulianDay(JD, calendar='standard'): """ returns a 'datetime-like' object given Julian Day. Julian Day is a fractional day with a resolution of 1 second. if calendar='standard' or 'gregorian' (default), Julian day follows Julian Calendar on and before 1582-10-5, Gregorian calendar after 1582-10-15. if calendar='proleptic_gregorian', Julian Day follows gregorian calendar. if calendar='julian', Julian Day follows julian calendar. The datetime object is a 'real' datetime object if the date falls in the Gregorian calendar (i.e. calendar='proleptic_gregorian', or calendar = 'standard'/'gregorian' and the date is after 1582-10-15). Otherwise, it's a 'phony' datetime object which is actually an instance of netcdftime.datetime. Algorithm: Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell, Virginia. p. 63 """ # based on redate.py by David Finlayson. julian = np.array(JD, dtype=float) if np.min(julian) < 0: raise ValueError('Julian Day must be positive') dayofwk = np.atleast_1d(np.int32(np.fmod(np.int32(julian + 1.5), 7))) # get the day (Z) and the fraction of the day (F) # add 0.000005 which is 452 ms in case of jd being after # second 23:59:59 of a day we want to round to the next day see issue #75 Z = np.atleast_1d(np.int32(np.round(julian + 0.00005))) F = np.atleast_1d(julian + 0.5 - Z).astype(np.float64) if calendar in ['standard', 'gregorian']: # MC # alpha = int((Z - 1867216.25)/36524.25) # A = Z + 1 + alpha - int(alpha/4) alpha = np.int32(((Z - 1867216.) - 0.25) / 36524.25) A = Z + 1 + alpha - np.int32(0.25 * alpha) # check if dates before oct 5th 1582 are in the array ind_before = np.where(julian < 2299160.5)[0] if len(ind_before) > 0: A[ind_before] = Z[ind_before] elif calendar == 'proleptic_gregorian': # MC # alpha = int((Z - 1867216.25)/36524.25) # A = Z + 1 + alpha - int(alpha/4) alpha = np.int32(((Z - 1867216.) - 0.25) / 36524.25) A = Z + 1 + alpha - np.int32(0.25 * alpha) elif calendar == 'julian': A = Z else: raise ValueError( 'unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s' % calendar) B = A + 1524 # MC # C = int((B - 122.1)/365.25) # D = int(365.25 * C) C = np.atleast_1d(np.int32(6680. + ((B - 2439870.) - 122.1) / 365.25)) D = np.atleast_1d(np.int32(365 * C + np.int32(0.25 * C))) E = np.atleast_1d(np.int32((B - D) / 30.6001)) # Convert to date day = np.clip(B - D - np.int64(30.6001 * E) + F, 1, None) nday = B - D - 123 dayofyr = nday - 305 ind_nday_before = np.where(nday <= 305)[0] if len(ind_nday_before) > 0: dayofyr[ind_nday_before] = nday[ind_nday_before] + 60 # MC # if E < 14: # month = E - 1 # else: # month = E - 13 # if month > 2: # year = C - 4716 # else: # year = C - 4715 month = E - 1 month[month > 12] = month[month > 12] - 12 year = C - 4715 year[month > 2] = year[month > 2] - 1 year[year <= 0] = year[year <= 0] - 1 # a leap year? leap = np.zeros(len(year)) leap[year % 4 == 0] = 1 if calendar == 'proleptic_gregorian': leap[(year % 100 == 0) & (year % 400 != 0)] = 0 elif calendar in ['standard', 'gregorian']: leap[(year % 100 == 0) & (year % 400 != 0) & (julian < 2299160.5)] = 0 inc_idx = np.where((leap == 1) & (month > 2))[0] dayofyr[inc_idx] = dayofyr[inc_idx] + leap[inc_idx] eps = np.clip((1e-12 * np.abs(Z)).astype(np.float64), np.float64(1e-12), None) hour = np.clip((F * 24. + eps).astype(np.int64), 0, 23) F -= hour / 24. minute = np.clip((F * 1440. + eps).astype(np.int64), 0, 59) # don't attempt microsecond accuracy, just round to nearest # second (issue #330) second = np.round(np.clip((F - minute / 1440.) * 86400., 0, None)) # convert year, month, day, hour, minute, second to int32 year = year.astype(np.int32) month = month.astype(np.int32) day = day.astype(np.int32) hour = hour.astype(np.int32) minute = minute.astype(np.int32) second = second.astype(np.int32) # check if input was scalar and change return accordingly isscalar = False try: JD[0] except: isscalar = True # return a 'real' datetime instance if calendar is gregorian. if calendar in 'proleptic_gregorian' or \ (calendar in ['standard', 'gregorian'] and len(ind_before) == 0): if not isscalar: return np.array([ real_datetime(*args) for args in zip(year, month, day, hour, minute, second) ]) else: return real_datetime(year[0], month[0], day[0], hour[0], minute[0], second[0]) else: # or else, return a 'datetime-like' instance. if not isscalar: return np.array([ datetime(*args) for args in zip(year, month, day, hour, minute, second, dayofwk, dayofyr) ]) else: return datetime(year[0], month[0], day[0], hour[0], minute[0], second[0], dayofwk[0], dayofyr[0])
def DateFromJulianDay(JD, calendar="standard"): """ returns a 'datetime-like' object given Julian Day. Julian Day is a fractional day with a resolution of 1 second. if calendar='standard' or 'gregorian' (default), Julian day follows Julian Calendar on and before 1582-10-5, Gregorian calendar after 1582-10-15. if calendar='proleptic_gregorian', Julian Day follows gregorian calendar. if calendar='julian', Julian Day follows julian calendar. The datetime object is a 'real' datetime object if the date falls in the Gregorian calendar (i.e. calendar='proleptic_gregorian', or calendar = 'standard'/'gregorian' and the date is after 1582-10-15). Otherwise, it's a 'phony' datetime object which is actually an instance of netcdftime.datetime. Algorithm: Meeus, Jean (1998) Astronomical Algorithms (2nd Edition). Willmann-Bell, Virginia. p. 63 """ # based on redate.py by David Finlayson. if JD < 0: raise ValueError, "Julian Day must be positive" dayofwk = int(math.fmod(int(JD + 1.5), 7)) (F, Z) = math.modf(JD + 0.5) Z = int(Z) if calendar in ["standard", "gregorian"]: if JD < 2299160.5: A = Z else: alpha = int((Z - 1867216.25) / 36524.25) A = Z + 1 + alpha - int(alpha / 4) elif calendar == "proleptic_gregorian": alpha = int((Z - 1867216.25) / 36524.25) A = Z + 1 + alpha - int(alpha / 4) elif calendar == "julian": A = Z else: raise ValueError, "unknown calendar, must be one of julian,standard,gregorian,proleptic_gregorian, got %s" % calendar B = A + 1524 C = int((B - 122.1) / 365.25) D = int(365.25 * C) E = int((B - D) / 30.6001) # Convert to date day = B - D - int(30.6001 * E) + F nday = B - D - 123 if nday <= 305: dayofyr = nday + 60 else: dayofyr = nday - 305 if E < 14: month = E - 1 else: month = E - 13 if month > 2: year = C - 4716 else: year = C - 4715 # a leap year? leap = 0 if year % 4 == 0: leap = 1 if calendar == "proleptic_gregorian" or (calendar in ["standard", "gregorian"] and JD >= 2299160.5): if year % 100 == 0 and year % 400 != 0: print year % 100, year % 400 leap = 0 if leap and month > 2: dayofyr = dayofyr + leap # Convert fractions of a day to time (dfrac, days) = math.modf(day / 1.0) (hfrac, hours) = math.modf(dfrac * 24.0) (mfrac, minutes) = math.modf(hfrac * 60.0) seconds = round(mfrac * 60.0) # seconds are rounded if seconds > 59: seconds = 0 minutes = minutes + 1 if minutes > 59: minutes = 0 hours = hours + 1 if hours > 23: hours = 0 days = days + 1 # return a 'real' datetime instance if calendar is gregorian. if calendar == "proleptic_gregorian" or (calendar in ["standard", "gregorian"] and JD >= 2299160.5): return real_datetime(year, month, int(days), int(hours), int(minutes), int(seconds)) else: # or else, return a 'datetime-like' instance. return datetime(year, month, int(days), int(hours), int(minutes), int(seconds), dayofwk, dayofyr)