Example #1
0
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)
Example #2
0
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
Example #3
0
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
Example #4
0
File: date.py Project: kyrre/weboob
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))
Example #5
0
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))
Example #6
0
 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)
Example #7
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]))
Example #8
0
def strptime(date_string, fmt):
    return real_datetime(*(time.strptime(date_string, fmt)[:6]))
Example #9
0
def strptime(date_string, fmt):
    return real_datetime(*(time.strptime(date_string, fmt)[:6]))
Example #10
0
    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)
Example #12
0
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])
Example #13
0
 def _to_real_datetime(self):
     return real_datetime(self._year, self._month, self._day, self._hour, self._minute, self._second)
Example #14
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:
            # 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)
Example #15
0
 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)
Example #16
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.

    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])
Example #17
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)
Example #18
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]))