Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ omit =
cf_units/_version.py
cf_units/etc/*
cf_units/tests/*
.eggs


[report]
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ cf_units/etc/site.cfg
\#*
\.\#*
*.swp
.coverage
.eggs
.pytest_cache
11 changes: 3 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,13 @@ install:

# Create the basic testing environment
# ------------------------------------
- conda config --set always_yes yes --set changeps1 no
- conda config --set show_channel_urls True
- conda config --set always_yes yes --set changeps1 no --set show_channel_urls True
- conda update --quiet conda
- conda config --add channels conda-forge
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conda-forge's udunits2 is newer, hope that this change is OK @bjlittle

- ENV_NAME='test-environment'
- conda create --quiet -n $ENV_NAME python=$TRAVIS_PYTHON_VERSION
- conda create --name $ENV_NAME python=$TRAVIS_PYTHON_VERSION udunits2 --file requirements.txt --file requirements-dev.txt
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Building the env in one go saves us some trouble. Sometimes conda does not respect channel preference when adding packages to an env.

- source activate $ENV_NAME

# Customise the testing environment.
# ----------------------------------
- conda install --quiet udunits2 --file requirements.txt --file requirements-dev.txt
- pip install coveralls

# Output debug info.
- conda list
- conda info -a
Expand Down
44 changes: 22 additions & 22 deletions cf_units/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
Units of measure.

Provision of a wrapper class to support Unidata/UCAR UDUNITS-2, and the
netcdftime calendar functionality.
cftime calendar functionality.

See also: `UDUNITS-2
<http://www.unidata.ucar.edu/software/udunits>`_.
Expand All @@ -36,7 +36,7 @@
import sys
import warnings

import netcdftime
import cftime
import numpy as np

from . import config
Expand Down Expand Up @@ -109,7 +109,7 @@
UT_DEFINITION]

#
# netcdftime constants
# cftime constants
#
CALENDAR_STANDARD = 'standard'
CALENDAR_GREGORIAN = 'gregorian'
Expand Down Expand Up @@ -319,7 +319,7 @@ def decode_time(time):

def julian_day2date(julian_day, calendar):
"""
Return a netcdftime datetime-like object representing the Julian day.
Return a cftime datetime-like object representing the Julian day.

If calendar is 'standard' or 'gregorian', Julian day follows
Julian calendar on and before 1582-10-5, Gregorian calendar after
Expand All @@ -332,7 +332,7 @@ def julian_day2date(julian_day, calendar):
the Gregorian calendar (i.e. calendar is 'proleptic_gregorian', or
calendar is '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.
of cftime.datetime.

Algorithm:
Meeus, Jean (1998) Astronomical Algorithms (2nd Edition).
Expand All @@ -346,7 +346,7 @@ def julian_day2date(julian_day, calendar):
Name of the calendar, see cf_units.CALENDARS.

Returns:
datetime or netcdftime.datetime.
datetime or cftime.datetime.

For example:

Expand All @@ -360,12 +360,12 @@ def julian_day2date(julian_day, calendar):

"""

return netcdftime.DateFromJulianDay(julian_day, calendar)
return cftime.DateFromJulianDay(julian_day, calendar)


def date2julian_day(date, calendar):
"""
Return the Julian day (resolution of 1 second) from a netcdftime
Return the Julian day (resolution of 1 second) from a cftime
datetime-like object.

If calendar is 'standard' or 'gregorian', Julian day follows Julian
Expand All @@ -380,7 +380,7 @@ def date2julian_day(date, calendar):

Args:

* date (netcdftime.date):
* date (cftime.date):
Date and time representation.
* calendar (string):
Name of the calendar, see cf_units.CALENDARS.
Expand All @@ -398,7 +398,7 @@ def date2julian_day(date, calendar):

"""

return netcdftime.JulianDayFromDate(date, calendar)
return cftime.JulianDayFromDate(date, calendar)


def date2num(date, unit, calendar):
Expand Down Expand Up @@ -449,7 +449,7 @@ def date2num(date, unit, calendar):

#
# ensure to strip out any 'UTC' postfix which is generated by
# UDUNITS-2 formatted output and causes the netcdftime parser
# UDUNITS-2 formatted output and causes the cftime parser
# to choke
#
unit_string = unit.rstrip(" UTC")
Expand All @@ -468,7 +468,7 @@ def _discard_microsecond(date):

Args:

* date (datetime.datetime or netcdftime.datetime):
* date (datetime.datetime or cftime.datetime):
Date value/s

Returns:
Expand All @@ -479,7 +479,7 @@ def _discard_microsecond(date):
shape = dates.shape
dates = dates.ravel()
# Create date objects of the same type returned by utime.num2date()
# (either datetime.datetime or netcdftime.datetime), discarding the
# (either datetime.datetime or cftime.datetime), discarding the
# microseconds
dates = np.array([d and d.__class__(d.year, d.month, d.day,
d.hour, d.minute, d.second)
Expand Down Expand Up @@ -548,7 +548,7 @@ def num2date(time_value, unit, calendar):

#
# ensure to strip out any 'UTC' postfix which is generated by
# UDUNITS-2 formatted output and causes the netcdftime parser
# UDUNITS-2 formatted output and causes the cftime parser
# to choke
#
unit_string = unit.rstrip(" UTC")
Expand All @@ -565,7 +565,7 @@ def _num2date_to_nearest_second(time_value, utime):

* time_value (float):
Numeric time value/s.
* utime (netcdftime.utime):
* utime (cftime.utime):
netcdf.utime object with which to perform the conversion/s.

Returns:
Expand All @@ -580,7 +580,7 @@ def _num2date_to_nearest_second(time_value, utime):
# down.
#
# Note that this behaviour is different to the num2date function in version
# 1.1 and earlier of netcdftime that didn't have microsecond precision. In
# 1.1 and earlier of cftime that didn't have microsecond precision. In
# those versions, a half-second value would be rounded up or down
# arbitrarily. It is probably not possible to replicate that behaviour with
# later versions, if one wished to do so for the sake of consistency.
Expand Down Expand Up @@ -969,7 +969,7 @@ def is_long_time_interval(self):
"""
Defines whether this unit describes a time unit with a long time
interval ("months" or "years"). These long time intervals *are*
supported by `UDUNITS2` but are not supported by `netcdftime`. This
supported by `UDUNITS2` but are not supported by `cftime`. This
discrepancy means we cannot run self.num2date() on a time unit with
a long time interval.

Expand Down Expand Up @@ -1832,7 +1832,7 @@ def convert(self, value, other, ctype=FLOAT64, inplace=False):

def utime(self):
"""
Returns a netcdftime.utime object which performs conversions of
Returns a cftime.utime object which performs conversions of
numeric time values to/from datetime objects given the current
calendar and unit time reference.

Expand All @@ -1841,7 +1841,7 @@ def utime(self):
i.e. 'hours since 1970-01-01 00:00:00'

Returns:
netcdftime.utime.
cftime.utime.

For example:

Expand All @@ -1856,7 +1856,7 @@ def utime(self):
if self.calendar is None:
raise ValueError('Unit has undefined calendar')

# `netcdftime` cannot parse long time intervals ("months" or "years").
# `cftime` cannot parse long time intervals ("months" or "years").
if self.is_long_time_interval():
interval = self.origin.split(' ')[0]
emsg = ('Time units with interval of "months", "years" '
Expand All @@ -1867,7 +1867,7 @@ def utime(self):
# ensure to strip out non-parsable 'UTC' postfix, which
# is generated by UDUNITS-2 formatted output
#
return netcdftime.utime(str(self).rstrip(" UTC"), self.calendar)
return cftime.utime(str(self).rstrip(" UTC"), self.calendar)

def date2num(self, date):
"""
Expand Down Expand Up @@ -1921,7 +1921,7 @@ def num2date(self, time_value):
if the date falls in the Gregorian calendar (i.e. the calendar
is 'standard', 'gregorian', or 'proleptic_gregorian' and the
date is after 1582-10-15). Otherwise a 'phoney' datetime-like
object (netcdftime.datetime) is returned which can handle dates
object (cftime.datetime) is returned which can handle dates
that don't exist in the Proleptic Gregorian calendar.

Works for scalars, sequences and numpy arrays. Returns a scalar
Expand Down
2 changes: 1 addition & 1 deletion cf_units/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# (C) British Crown Copyright 2010 - 2015, Met Office
# (C) British Crown Copyright 2010 - 2018, Met Office
#
# This file is part of cf_units.
#
Expand Down
18 changes: 9 additions & 9 deletions cf_units/tests/integration/test__num2date_to_nearest_second.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@

import numpy as np
import numpy.testing
import netcdftime
import cftime

from cf_units import _num2date_to_nearest_second, Unit


class Test(unittest.TestCase):
def setup_units(self, calendar):
self.useconds = netcdftime.utime('seconds since 1970-01-01', calendar)
self.uminutes = netcdftime.utime('minutes since 1970-01-01', calendar)
self.uhours = netcdftime.utime('hours since 1970-01-01', calendar)
self.udays = netcdftime.utime('days since 1970-01-01', calendar)
self.useconds = cftime.utime('seconds since 1970-01-01', calendar)
self.uminutes = cftime.utime('minutes since 1970-01-01', calendar)
self.uhours = cftime.utime('hours since 1970-01-01', calendar)
self.udays = cftime.utime('days since 1970-01-01', calendar)

def check_dates(self, nums, utimes, expected):
for num, utime, exp in zip(nums, utimes, expected):
Expand All @@ -50,14 +50,14 @@ def check_timedelta(self, nums, utimes, expected):
self.assertEqual((delta.days, seconds), exp)

def test_scalar(self):
utime = netcdftime.utime('seconds since 1970-01-01', 'gregorian')
utime = cftime.utime('seconds since 1970-01-01', 'gregorian')
num = 5.
exp = datetime.datetime(1970, 1, 1, 0, 0, 5)
res = _num2date_to_nearest_second(num, utime)
self.assertEqual(exp, res)

def test_sequence(self):
utime = netcdftime.utime('seconds since 1970-01-01', 'gregorian')
utime = cftime.utime('seconds since 1970-01-01', 'gregorian')
nums = [20., 40., 60., 80, 100.]
exp = [datetime.datetime(1970, 1, 1, 0, 0, 20),
datetime.datetime(1970, 1, 1, 0, 0, 40),
Expand All @@ -68,15 +68,15 @@ def test_sequence(self):
np.testing.assert_array_equal(exp, res)

def test_multidim_sequence(self):
utime = netcdftime.utime('seconds since 1970-01-01', 'gregorian')
utime = cftime.utime('seconds since 1970-01-01', 'gregorian')
nums = [[20., 40., 60.],
[80, 100., 120.]]
exp_shape = (2, 3)
res = _num2date_to_nearest_second(nums, utime)
self.assertEqual(exp_shape, res.shape)

def test_masked_ndarray(self):
utime = netcdftime.utime('seconds since 1970-01-01', 'gregorian')
utime = cftime.utime('seconds since 1970-01-01', 'gregorian')
nums = np.ma.masked_array([20., 40., 60.], [False, True, False])
exp = [datetime.datetime(1970, 1, 1, 0, 0, 20),
None,
Expand Down
4 changes: 2 additions & 2 deletions cf_units/tests/integration/test_date2num.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# (C) British Crown Copyright 2016 - 2017, Met Office
# (C) British Crown Copyright 2016 - 2018, Met Office
#
# This file is part of cf_units.
#
Expand All @@ -24,7 +24,7 @@

import numpy as np
import numpy.testing
import netcdftime
import cftime

from cf_units import date2num, Unit

Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
coveralls
pep8
pip
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
six
netcdf4
cftime
cython
numpy
# udunits2 cannot be installed with pip, and it is expected to be installed separately.