def setUp(self): self.standardtime = self.TestTime(datetime(1950, 1, 1), 366, 24, 'hours since 1900-01-01', 'standard') self.time_vars = {} self.time_vars['time'] = NetCDFTimeVariable( values=self.standardtime, units='hours since 1900-01-01') self.first_timestamp = datetime(2000, 1, 1) units = 'days since 1901-01-01' self.time_vars['time2'] = NetCDFTimeVariable( values=date2num([self.first_timestamp], units), units=units) ntimes = 21 units = "seconds since 1970-01-01 00:00:00" date = datetime(2037, 1, 1, 0) dates = [date] for ndate in range(ntimes-1): date += (ndate+1)*timedelta(hours=1) dates.append(date) self.time_vars['time3'] = NetCDFTimeVariable( values=date2num(dates, units), units=units)
def setUp(self): self.standardtime = self.TestTime(datetime(1950, 1, 1), 366, 24, 'hours since 1900-01-01', 'standard') self.file = tempfile.NamedTemporaryFile(suffix='.nc', delete=False).name f = Dataset(self.file, 'w') f.createDimension('time', None) time = f.createVariable('time', float, ('time', )) time.units = 'hours since 1900-01-01' time[:] = self.standardtime[:] f.createDimension('time2', 1) time2 = f.createVariable('time2', 'f8', ('time2', )) time2.units = 'days since 1901-01-01' self.first_timestamp = datetime(2000, 1, 1) time2[0] = date2num(self.first_timestamp, time2.units) ntimes = 21 f.createDimension("record", ntimes) time3 = f.createVariable("time3", numpy.int32, ("record", )) time3.units = "seconds since 1970-01-01 00:00:00" date = datetime(2037, 1, 1, 0) dates = [date] for ndate in range(ntimes - 1): date += (ndate + 1) * timedelta(hours=1) dates.append(date) time3[:] = date2num(dates, time3.units) f.close()
def test_select_nc(self): f = Dataset(self.file, "r") nutime = f.variables["time"] dates = [datetime(1950, 1, 2, 6), datetime(1950, 1, 3), datetime(1950, 1, 3, 18)] t = date2index(dates, nutime, select="before") assert_equal(t, [1, 2, 2]) t = date2index(dates, nutime, select="after") assert_equal(t, [2, 2, 3]) t = date2index(dates, nutime, select="nearest") assert_equal(t, [1, 2, 3]) # Test dates outside the support with select t = date2index(datetime(1949, 12, 1), nutime, select="nearest") assert_equal(t, 0) t = date2index(datetime(1978, 1, 1), nutime, select="nearest") assert_equal(t, 365) # Test dates outside the support with before self.assertRaises(ValueError, date2index, datetime(1949, 12, 1), nutime, select="before") t = date2index(datetime(1978, 1, 1), nutime, select="before") assert_equal(t, 365) # Test dates outside the support with after t = date2index(datetime(1949, 12, 1), nutime, select="after") assert_equal(t, 0) self.assertRaises(ValueError, date2index, datetime(1978, 1, 1), nutime, select="after") # test microsecond and millisecond units unix_epoch = "milliseconds since 1970-01-01T00:00:00Z" from netCDF4 import date2num d = datetime(2038, 1, 19, 3, 14, 7) millisecs = int(date2num(d, unix_epoch, calendar="proleptic_gregorian")) assert_equal(millisecs, (2 ** 32 / 2 - 1) * 1000) unix_epoch = "microseconds since 1970-01-01T00:00:00Z" microsecs = int(date2num(d, unix_epoch)) assert_equal(microsecs, (2 ** 32 / 2 - 1) * 1000000) # test microsecond accuracy in date2num/num2date roundtrip # note: microsecond accuracy lost for time intervals greater # than about 270 years. from dateutil.tz import tzutc units = "microseconds since 1776-07-04 00:00:00-12:00" dates = [ datetime(1962, 10, 27, 6, 1, 30, 9001), datetime(1993, 11, 21, 12, 5, 25, 999), datetime(1995, 11, 25, 18, 7, 59, 999999), ] times2 = date2num(dates, units) dates2 = num2date(times2, units) for date, date2 in zip(dates, dates2): assert_equal(date.replace(tzinfo=tzutc()), date2) f.close()
def test_select_nc(self): f = Dataset(self.file, 'r') nutime = f.variables['time'] dates = [datetime(1950, 1, 2, 6), datetime( 1950, 1, 3), datetime(1950, 1, 3, 18)] t = date2index(dates, nutime, select='before') assert_equal(t, [1, 2, 2]) t = date2index(dates, nutime, select='after') assert_equal(t, [2, 2, 3]) t = date2index(dates, nutime, select='nearest') assert_equal(t, [1, 2, 3]) # Test dates outside the support with select t = date2index(datetime(1949, 12, 1), nutime, select='nearest') assert_equal(t, 0) t = date2index(datetime(1978, 1, 1), nutime, select='nearest') assert_equal(t, 365) # Test dates outside the support with before self.assertRaises( ValueError, date2index, datetime(1949, 12, 1), nutime, select='before') t = date2index(datetime(1978, 1, 1), nutime, select='before') assert_equal(t, 365) # Test dates outside the support with after t = date2index(datetime(1949, 12, 1), nutime, select='after') assert_equal(t, 0) self.assertRaises( ValueError, date2index, datetime(1978, 1, 1), nutime, select='after') # test microsecond and millisecond units unix_epoch = "milliseconds since 1970-01-01T00:00:00Z" from netCDF4 import date2num d = datetime(2038, 1, 19, 3, 14, 7) millisecs = int( date2num(d, unix_epoch, calendar='proleptic_gregorian')) assert_equal(millisecs, (2 ** 32 / 2 - 1) * 1000) unix_epoch = "microseconds since 1970-01-01T00:00:00Z" microsecs = int(date2num(d, unix_epoch)) assert_equal(microsecs, (2 ** 32 / 2 - 1) * 1000000) # test microsecond accuracy in date2num/num2date roundtrip # note: microsecond accuracy lost for time intervals greater # than about 270 years. from dateutil.tz import tzutc units = 'microseconds since 1776-07-04 00:00:00-12:00' dates =\ [datetime(1962, 10, 27, 6, 1, 30, 9001), datetime( 1993, 11, 21, 12, 5, 25, 999), datetime(1995, 11, 25, 18, 7, 59, 999999)] times2 = date2num(dates, units) dates2 = num2date(times2, units) for date, date2 in zip(dates, dates2): assert_equal(date.replace(tzinfo=tzutc()), date2) f.close()
def fill(self,data,tind='next',quiet=1): ''' Fills model netcdf climatology file (data can be provided by prognostic.data2roms ''' nc=netcdf.Pync(self.filename,'w') if tind=='next': tind=nc.dims['time'] if not quiet: print 'filling clm file %s' % self.filename # about time: try: date=dts.parse_date(data['date']) time=netcdftime.date2num(date,self.tunits) except: time=data['date'] # date as number! for i in nc.varnames: if i.endswith('time'): if not quiet: print ' -- %s tind=%d %f' % (i,tind,time) nc.vars[i][tind]=time names='temp','salt','u','v','ubar','vbar','zeta' for i in names: if not quiet: print ' %s' % i nc.vars[i][tind,...]=data[i] nc.close()
def tick_values(self, vmin, vmax): vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander=1e-7, tiny=1e-13) lower = netcdftime.num2date(vmin, self.date_unit, self.calendar) upper = netcdftime.num2date(vmax, self.date_unit, self.calendar) self.ndays = abs(vmax - vmin) resolution, n = self.compute_resolution(vmin, vmax, lower, upper) if resolution == 'YEARLY': # TODO START AT THE BEGINNING OF A DECADE/CENTURY/MILLENIUM as appropriate. years = self._max_n_locator.tick_values(lower.year, upper.year) ticks = [netcdftime.datetime(int(year), 1, 1) for year in years] elif resolution == 'MONTHLY': # TODO START AT THE BEGINNING OF A DECADE/CENTURY/MILLENIUM as appropriate. months_offset = self._max_n_locator.tick_values(0, n) ticks = [] for offset in months_offset: year = lower.year + np.floor((lower.month + offset) / 12) month = ((lower.month + offset) % 12) + 1 ticks.append(netcdftime.datetime(int(year), int(month), 1)) elif resolution == 'DAILY': # TODO: It would be great if this favoured multiples of 7. days = self._max_n_locator_days.tick_values(vmin, vmax) ticks = [netcdftime.num2date(dt, self.date_unit, self.calendar) for dt in days] elif resolution == 'HOURLY': hour_unit = 'hours since 2000-01-01' in_hours = netcdftime.date2num([lower, upper], hour_unit, self.calendar) hours = self._max_n_locator.tick_values(in_hours[0], in_hours[1]) ticks = [netcdftime.num2date(dt, hour_unit, self.calendar) for dt in hours] elif resolution == 'MINUTELY': minute_unit = 'minutes since 2000-01-01' in_minutes = netcdftime.date2num([lower, upper], minute_unit, self.calendar) minutes = self._max_n_locator.tick_values(in_minutes[0], in_minutes[1]) ticks = [netcdftime.num2date(dt, minute_unit, self.calendar) for dt in minutes] elif resolution == 'SECONDLY': second_unit = 'seconds since 2000-01-01' in_seconds = netcdftime.date2num([lower, upper], second_unit, self.calendar) seconds = self._max_n_locator.tick_values(in_seconds[0], in_seconds[1]) ticks = [netcdftime.num2date(dt, second_unit, self.calendar) for dt in seconds] else: raise ValueError('Resolution {} not implemented yet.'.format(resolution)) return netcdftime.date2num(ticks, self.date_unit, self.calendar)
def generate_cube(): """Generates a cube containing month numbers as data, so January always has data value 1. """ data = np.array([i+1 for i in xrange(12)]*2) dates = np.array([netcdftime.datetime(2000+(i/12), (i % 12)+1, 1) for i in xrange(len(data))]) time = netcdftime.date2num(dates, 'days since 2000-01-01') time_coord = iris.coords.DimCoord(time, standard_name='time', units='days since 2000-01-01') dim_coords_and_dims = [(time_coord, 0)] cube = iris.cube.Cube(data, dim_coords_and_dims=dim_coords_and_dims, long_name='dummy data') return cube
def setUp(self): self.standardtime = self.TestTime(datetime(1950, 1, 1), 366, 24, "hours since 1900-01-01", "standard") self.file = tempfile.mktemp(".nc") f = Dataset(self.file, "w") f.createDimension("time", None) time = f.createVariable("time", float, ("time",)) time.units = "hours since 1900-01-01" time[:] = self.standardtime[:] f.createDimension("time2", 1) time2 = f.createVariable("time2", "f8", ("time2",)) time2.units = "days since 1901-01-01" self.first_timestamp = datetime(2000, 01, 01) time2[0] = date2num(self.first_timestamp, time2.units) f.close()
def setUp(self): self.standardtime = self.TestTime(datetime(1950, 1, 1), 366, 24, 'hours since 1900-01-01', 'standard') self.file = tempfile.mktemp(".nc") f = Dataset(self.file, 'w') f.createDimension('time', None) time = f.createVariable('time', float, ('time',)) time.units = 'hours since 1900-01-01' time[:] = self.standardtime[:] f.createDimension('time2', 1) time2 = f.createVariable('time2', 'f8', ('time2',)) time2.units = 'days since 1901-01-01' self.first_timestamp = datetime(2000, 1, 1) time2[0] = date2num(self.first_timestamp, time2.units) f.close()
def __init__(self,filename,grid,sparams,**kargs): if not 'type' in kargs.keys(): kargs['type'] = 'ROMS Initial file' if not 'title' in kargs.keys(): kargs['title'] = 'ROMS Initial file' GenCommon.__init__(self,filename,grid,sparams,**kargs) date = 0 if 'date' in kargs.keys(): date = kargs['date'] self.date = date # about time: try: self.date=dts.parse_date(self.date) self.time=netcdftime.date2num(self.date,self.tunits) except: self.time=self.date # date as number!
def setUp(self): self.standardtime = self.TestTime(datetime(1950, 1, 1), 366, 24, 'hours since 1900-01-01', 'standard') self.file = tempfile.mktemp(".nc") f = Dataset(self.file,'w') f.createDimension('time', None) time = f.createVariable('time', float, ('time',)) time.units = 'hours since 1900-01-01' time[:] = self.standardtime[:] f.createDimension('time2', 1) time2 = f.createVariable('time2', 'f8', ('time2',)) time2.units = 'days since 1901-01-01' self.first_timestamp = datetime(2000, 1, 1) time2[0] = date2num(self.first_timestamp, time2.units) f.close()
def convert(cls, value, unit, axis): if isinstance(value, np.ndarray): # Don't do anything with numeric types. if value.dtype != np.object: return value first_value = value[0] else: # Don't do anything with numeric types. if munits.ConversionInterface.is_numlike(value): return value first_value = value if not hasattr(first_value, 'calendar'): raise ValueError('A "calendar" attribute must be attached to ' 'netcdftime object to understand them properly.') return netcdftime.date2num(value, cls.standard_unit, calendar=first_value.calendar)
def __init__(self, start, n, step, units, calendar='standard'): """Create an object that fakes a netCDF time variable. Internally, this object has a _data array attribute whose values corresponds to dates in the given units and calendar. `start`, `n` and `step` define the starting date, the length of the array and the distance between each date (in units). :Example: >>> t = TestTime(datetime(1989, 2, 18), 45, 6, 'hours since 1979-01-01') >>> print num2date(t[1], t.units) 1989-02-18 06:00:00 """ self.units = units self.calendar = calendar t0 = date2num(start, units, calendar) self._data = (t0 + numpy.arange(n) * step).astype('float') self.dtype = numpy.float
def __init__(self, start, n, step, units, calendar='standard'): """Create an object that fakes a netCDF time variable. Internally, this object has a _data array attribute whose values corresponds to dates in the given units and calendar. `start`, `n` and `step` define the starting date, the length of the array and the distance between each date (in units). :Example: >>> t = TestTime(datetime(1989, 2, 18), 45, 6, 'hours since 1979-01-01') >>> print num2date(t[1], t.units) 1989-02-18 06:00:00 """ self.units = units self.calendar = calendar t0 = date2num(start, units, calendar) self._data = (t0 + numpy.arange(n)*step).astype('float') self.dtype = numpy.float
def generate_cube(): """Generates a cube containing month numbers as data, so January always has data value 1. """ data = np.array([i + 1 for i in xrange(12)] * 2) dates = np.array([ netcdftime.datetime(2000 + (i / 12), (i % 12) + 1, 1) for i in xrange(len(data)) ]) time = netcdftime.date2num(dates, 'days since 2000-01-01') time_coord = iris.coords.DimCoord(time, standard_name='time', units='days since 2000-01-01') dim_coords_and_dims = [(time_coord, 0)] cube = iris.cube.Cube(data, dim_coords_and_dims=dim_coords_and_dims, long_name='dummy data') return cube
def fill(self,data,tind='next',quiet=1): ''' Fills model netcdf boundary conditions (data can be provided by prognostic.data2romsbry ''' nc=netcdf.Pync(self.filename,'w') if tind=='next': tind=nc.dims['time'] if not quiet: print 'filling bry file %s' % self.filename # about time: try: date=dts.parse_date(data['date']) time=netcdftime.date2num(date,self.tunits) except: time=data['date'] # date as number! for i in nc.varnames: if i.endswith('time'): if not quiet: print ' -- %s tind=%d %f' % (i,tind,time) nc.vars[i][tind]=time names='temp','salt','u','v','ubar','vbar','zeta' if self.addxz: names=list(names)+['dist','distu','distv','depth','depthu','depthv'] for i in names: for j in 'north','south','east','west': vname=i+'_'+j if vname in nc.varnames: if vname.startswith('dist'): if tind==0: if not quiet: print ' %s' % vname nc.vars[vname][:]=data[vname] # not time dependent else: if not quiet: print ' %s' % vname nc.vars[vname][tind,...]=data[vname] nc.close()
def fill(self,data,quiet=1): ''' Fills model netcdf river forcing file The input data shoud have as keys the river names (with river runoff, temp, salt, vshape, xi,eta and direction) and time (datetime) Example: data['amazonas']=q,temp,salt,vshape,Xi,Eta,Dir data['time']=np.arange(20) ''' # convert time to tunits: time=data['time'] for i in range(len(time)): time[i]=netcdftime.date2num(time[i],self.tunits) nc=netcdf.Pync(self.fname,'a') if not quiet: print ' -- filling time...' for i in range(len(time)): nc.vars['river_time'][i]=time[i] cont=-1 for k in data.keys(): if k=='time': continue cont+=1 q,temp,salt,vshape,Xi,Eta,Dir=data[k] if not quiet: print ' -- filling river',cont nc.vars['river'][cont] = cont nc.vars['river_Xposition'][cont] = Xi nc.vars['river_Eposition'][cont] = Eta nc.vars['river_direction'][cont] = Dir nc.vars['river_Vshape'][:,cont] = vshape nc.vars['river_transport'][:,cont] = q nc.vars['river_temp'][:,:,cont] = temp nc.vars['river_salt'][:,:,cont] = salt nc.close()
def encode_datetime(d): return np.nan if d is None else nctime.date2num(d, units, calendar)
def date2dec(calendar='standard', units=None, excelerr=True, yr=1, mo=1, dy=1, hr=0, mi=0, sc=0, ascii=None, eng=None): """ Converts numpy arrays with calendar date into numpy arrays with decimal date. Supported calendar formats are standard, gregorian, julian, proleptic_gregorian, excel1900, excel1904, 365_day, noleap, 366_day, all_leap, 360_day, decimal, or decimal360 Input is year, month day, hour, minute, second or a combination of them. ASCII input is possible, too. Output is decimal date with day as unit. Requires 'netcdftime.py' from the module netcdftime available at: http://netcdf4-python.googlecode.com Definition ---------- def date2dec(calendar = 'standard', units=None, excelerr = True, yr=1, mo=1, dy=1, hr=0, mi=0, sc=0, ascii=None, eng=None): Input ----- yr -> input array with year mo -> input array with month dy -> input array with day hr -> input array with hour mi -> input array with minute sc -> input array with second ascii -> input array with strings of the format 'dd.mm.yyyy hh:mm:ss'. If hour, minutes and/or seconds are missing, they will be set to 00. If ascii input is chosen by user, other inputs will be neglected. ascii and eng are mutually exclusive. eng -> input array with strings of the format 'yyyy-mm-dd hh:mm:ss'. If hour, minutes and/or seconds are missing, they will be set to 00. If eng input is chosen, other inputs will be neglected. ascii and eng are mutually exclusive. Parameters ---------- calendar -> Input date format. Default value is 'standard'. 'standard', 'gregorian' = Input date is standard format. Input is in julian calendar from 01.01.-4712 12:00:00 (BC) until 05.03.1583 00:00:00 and gregorian calendar from 15.03.1583 00:00:00 until now. Missing 10 days don't exsist. 'julian' = Input date is julian format. Input is in julian calendar from 01.01.-4712 12:00:00 (BC) until now. 'proleptic_gregorian' = Input date is gregorian format. Input is in gregorian calendar from 01.01.0000 00:00:00 until now. 'excel1900' = Input date is excel 1900 format. Input date is excel date with its units at 01.01.1900 00:00:00 until now. 'excel1904' = Input date is excel 1904 (lotus) format. Input date is excel date with its units at 01.01.1904 00:00:00 until now. '365_day', 'noleap' = Input date is 365 days format. Input date consists of common years only (No leap years) with its units at 01.01.0001 00:00:00 until now. '366_day', 'all_leap' = Input date is 366 days format. Input date consists of leap years only (No common years) with its units at 01.01.0001 00:00:00 until now. '360_day' = Input date is 360 days format. Input date consists of years with only 360 days (30 days per month)with its units at 'decimal' = Output is decimal year. 'decimal360' = Output is decimal year with a year of 360 days, i.e. 12 month with 30 days each. Optional Arguments ------------------ units -> Time units can be set by user. Input must be a string in the format 'days since yyyy-mm-dd hh:mm:ss'. Default values are set automatically. excelerr -> In Excel the year 1900 is normally considered as leap year, which is wrong. By default, this error is taken into account (excelerr = True). For excelerr = False, 1900 is considered as no leap year. Output ------ output -> Output numpy array with decimal date. Restrictions ------------ Most versions of datetime do not support neagtive years, i.e. Julian days < 1721423.5 = 01.01.0001 00:00. There is an issue in netcdftime version < 0.9.5 in proleptic_gregorian for dates before year 301: ufz.dec2date(ufz.date2dec(ascii='01.01.0300 00:00:00', calendar='proleptic_gregorian'), calendar='proleptic_gregorian') [300, 1, 2, 0, 0, 0] ufz.dec2date(ufz.date2dec(ascii='01.01.0301 00:00:00', calendar='proleptic_gregorian'), calendar='proleptic_gregorian') [301, 1, 1, 0, 0, 0] List input is only supported up to 2 dimensions. Requires 'netcdftime.py' from module netcdftime available at: http://netcdf4-python.googlecode.com Examples -------- #calendar = 'standard' # Some implementations of datetime have problems with negative years >>> import datetime >>> if datetime.MINYEAR > 0: ... print('The minimum year in your datetime implementation is ', datetime.MINYEAR) ... print('i.e. it does not support negative years (BC).') >>> if datetime.MINYEAR > 0: ... year = np.array([2000, 1810, 1630, 1510, 1271, 619, 2, 1]) ... else: ... year = np.array([2000, 1810, 1630, 1510, 1271, 619, -1579, -4712]) >>> month = np.array([1, 4, 7, 9, 3, 8, 8, 1]) >>> day = np.array([5, 24, 15, 20, 18, 27, 23, 1]) >>> hour = np.array([12, 16, 10, 14, 19, 11, 20, 12]) >>> minute = np.array([30, 15, 20, 35, 41, 8, 3, 0]) >>> second = np.array([15, 10, 40, 50, 34, 37, 41, 0]) >>> decimal = date2dec(calendar = 'standard', yr=year, mo=month, dy=day, hr=hour, mi=minute, sc=second) >>> from autostring import astr >>> nn = year.size >>> print(astr(decimal[:nn/2], 14, pp=True)) ['2.45154902100694e+06' '2.38226217719907e+06' '2.31660093101852e+06' '2.27284810821759e+06'] >>> print(astr(decimal[nn/2:nn-2], 14,pp=True)) ['2.18536732053241e+06' '1.94738596431713e+06'] >>> decimal = date2dec(calendar='standard', yr=year, mo=6, dy=15, hr=12, mi=minute, sc=second) >>> print(astr(decimal[:nn/2],14,pp=True)) ['2.45171102100694e+06' '2.38231401053241e+06' '2.31657101435185e+06' '2.27275102488426e+06'] >>> print(astr(decimal[nn/2:nn-2],14,pp=True)) ['2.18545602886574e+06' '1.94731300598380e+06'] # ascii input >>> if datetime.MINYEAR > 0: ... a = np.array(['05.01.2000 12:30:15', '24.04.1810 16:15:10', '15.07.1630 10:20:40', '20.09.1510 14:35:50', ... '18.03.1271 19:41:34', '27.08. 619 11:08:37', '23.08.0002 20:03:41', '01.01.0001 12:00:00']) ... else: ... a = np.array(['05.01.2000 12:30:15', '24.04.1810 16:15:10', '15.07.1630 10:20:40', '20.09.1510 14:35:50', ... '18.03.1271 19:41:34', '27.08. 619 11:08:37', '23.08.-1579 20:03:41', '01.01.-4712 12:00:00']) >>> decimal = date2dec(calendar='standard', ascii=a) >>> nn = a.size >>> print(astr(decimal[:nn/2],14,pp=True)) ['2.45154902100694e+06' '2.38226217719907e+06' '2.31660093101852e+06' '2.27284810821759e+06'] >>> print(astr(decimal[nn/2:nn-2],14,pp=True)) ['2.18536732053241e+06' '1.94738596431713e+06'] # calendar = 'julian' >>> decimal = date2dec(calendar='julian', ascii=a) >>> print(astr(decimal[:nn/2],14,pp=True)) ['2.45156202100694e+06' '2.38227417719907e+06' '2.31661093101852e+06' '2.27284810821759e+06'] >>> print(astr(decimal[nn/2:nn-2],14,pp=True)) ['2.18536732053241e+06' '1.94738596431713e+06'] # calendar = 'proleptic_gregorian' >>> decimal = date2dec(calendar='proleptic_gregorian', ascii=a) >>> print(astr(decimal[:nn/2], 7, pp=True)) ['730123.5210069' '660836.6771991' '595175.4310185' '551412.6082176'] >>> print(astr(decimal[nn/2:nn-2], 7, pp=True)) ['463934.8205324' '225957.4643171'] # calendar = 'excel1900' WITH excelerr=True -> 1900 considered as leap year >>> d = np.array(['05.01.2000 12:30:15', '27.05.1950 16:25:10', '13.08.1910 10:40:55', ... '01.03.1900 00:00:00', '29.02.1900 00:00:00', '28.02.1900 00:00:00', ... '01.01.1900 00:00:00']) >>> decimal = date2dec(calendar='excel1900', ascii=d) >>> nn = d.size >>> print(astr(decimal[:nn/2], 7, pp=True)) ['36530.5210069' '18410.6841435' ' 3878.4450810'] >>> print(astr(decimal[nn/2:],14,pp=True)) ['61.00000000000000' '60.00000000000000' '59.00000000000000' ' 1.00000000000000'] # calendar = 'excel1900' WITH excelerr = False -> 1900 is NO leap year >>> decimal = date2dec(calendar='excel1900', ascii=d, excelerr=False) >>> print(astr(decimal[:nn/2], 7, pp=True)) ['36529.5210069' '18409.6841435' ' 3877.4450810'] >>> print(astr(decimal[nn/2:],14,pp=True)) ['60.00000000000000' '60.00000000000000' '59.00000000000000' ' 1.00000000000000'] # calendar = 'excel1904' >>> decimal = date2dec(calendar='excel1904', ascii=d[:nn/2]) >>> print(astr(decimal[:nn/2], 7, pp=True)) ['35069.5210069' '16949.6841435' ' 2417.4450810'] # calendar = '365_day' >>> g = np.array(['18.08.1972 12:30:15', '25.10.0986 12:30:15', '28.11.0493 22:20:40', '01.01.0001 00:00:00']) >>> decimal = date2dec(calendar='365_day', ascii=g) >>> nn = g.size >>> print(astr(decimal[:nn],14,pp=True)) ['719644.52100694458932' '359822.52100694435649' '179911.93101851851679' ' 0.00000000000000'] # calendar = '366_day' >>> decimal = date2dec(calendar='366_day', ascii=g) >>> print(astr(decimal[:nn],14,pp=True)) ['721616.52100694458932' '360808.52100694435649' '180404.93101851851679' ' 0.00000000000000'] # 360_day does not work with netcdftime.py version equal or below 0.9.2 # calendar = '360_day' >>> decimal = date2dec(calendar='360_day', ascii=g) >>> print(astr(decimal[:nn],14,pp=True)) ['709787.52100694458932' '354894.52100694435649' '177447.93101851851679' ' 0.00000000000000'] >>> print(astr(date2dec(yr=1992, mo=1, dy=26, hr=2, mi=0, sc=0, calendar='decimal'),14,pp=True)) 1992.06853370763201 >>> print(astr(date2dec(ascii='26.01.1992 02:00', calendar='decimal360'),14,pp=True)) 1992.06967593592572 >>> print(astr(date2dec(ascii=['26.01.1992 02:00','26.01.1992 02:00'], calendar='decimal360'),14,pp=True)) ['1992.06967593592572' '1992.06967593592572'] >>> print(astr(date2dec(yr=[1992,1992], mo=1, dy=26, hr=2, mi=0, sc=0, calendar='decimal360'),14,pp=True)) ['1992.06967593592572' '1992.06967593592572'] >>> print(astr(date2dec(yr=np.array([1992,1992]), mo=1, dy=26, hr=2, mi=0, sc=0, calendar='decimal360'), ... 14,pp=True)) ['1992.06967593592572' '1992.06967593592572'] >>> print(astr(date2dec(ascii=[['26.01.1992 02:00','26.01.1992 02:00'], ... ['26.01.1992 02:00','26.01.1992 02:00'], ... ['26.01.1992 02:00','26.01.1992 02:00']], calendar='decimal360'),14,pp=True)) [['1992.06967593592572' '1992.06967593592572'] ['1992.06967593592572' '1992.06967593592572'] ['1992.06967593592572' '1992.06967593592572']] >>> print((date2dec(ascii='01.03.2003 00:00:00') - date2dec(ascii='01.03.2003')) == 0.) True License ------- This file is part of the UFZ Python package. The UFZ Python package is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The UFZ Python package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the UFZ makefile project (cf. gpl.txt and lgpl.txt). If not, see <http://www.gnu.org/licenses/>. Copyright 2010-2013 Arndt Piayda, Matthias Cuntz History ------- Written AP, Jun 2010 Modified MC, Feb 2012 - All input can be scalar, list or array, also a mix - Changed checks for easier extension - decimal, decimal360 MC, Dec 2012 - change unit of proleptic_gregorian from 'days since 0001-01-01 00:00:00' to 'days since 0001-01-00 00:00:00' MC, Feb 2013 - solved Excel leap year problem. MC, Feb 2013 - ported to Python 3 MC, Jul 2013 - ascii/eng without time defaults to 00:00:00 MC, Oct 2013 - Excel starts at 1 not at 0 MC, Oct 2013 - units bugs, e.g. 01.01.0001 was substracted if Julian calendar even with units MC, Nov 2013 - removed remnant of time treatment before time check in eng keyword MC, Jun 2015 - adapted to new netCDF4/netcdftime (>= v1.0) and datetime (>= Python v2.7.9) MC, Oct 2015 - call date2num with list instead of single netCDF4.datetime objects """ # # Checks calendars = [ 'standard', 'gregorian', 'julian', 'proleptic_gregorian', 'excel1900', 'excel1904', '365_day', 'noleap', '366_day', 'all_leap', '360_day', 'decimal', 'decimal360' ] is1 = False try: import netcdftime as nt testit = nt.__version__ except: is1 = True if not is1: if ((nt.__version__ <= '0.9.2') & (calendar == '360_day')): raise ValueError( "date2dec error: Your version of netcdftime.py is equal" " or below 0.9.2. The 360_day calendar does not work with" " arrays here. Please download a newer one.") else: import netCDF4 as nt # calendar = calendar.lower() if (calendar not in calendars): raise ValueError("date2dec error: Wrong calendar!" " Choose: " + ''.join([i + ' ' for i in calendars])) # if ascii input is given by user, other input will be neglected # calculation of input size and shape if (ascii is not None) and (eng is not None): raise ValueError( "date2dec error: 'ascii' and 'eng' mutually exclusive") if ascii is not None: islist = type(ascii) != type(np.array(ascii)) isarr = np.ndim(ascii) if (islist & (isarr > 2)): raise ValueError( "date2dec error: ascii input is list > 2D; Use array input") if isarr == 0: ascii = np.array([ascii]) else: ascii = np.array(ascii) insize = ascii.size outsize = insize outshape = ascii.shape asciifl = ascii.flatten() timeobj = np.zeros(insize, dtype=object) # slicing of ascii strings to implement in datetime object. missing times # will be set to 00. yr = np.zeros(insize, dtype=np.int) mo = np.zeros(insize, dtype=np.int) dy = np.zeros(insize, dtype=np.int) hr = np.zeros(insize, dtype=np.int) mi = np.zeros(insize, dtype=np.int) sc = np.zeros(insize, dtype=np.int) for i in range(insize): aa = asciifl[i].split('.') dy[i] = int(aa[0]) mo[i] = int(aa[1]) tail = aa[2].split() yr[i] = int(tail[0]) if len(tail) > 1: tim = tail[1].split(':') hr[i] = int(tim[0]) if len(tim) > 1: mi[i] = int(tim[1]) else: mi[i] = 00 if len(tim) > 2: sc[i] = int(tim[2]) else: sc[i] = 00 else: hr[i] = 00 mi[i] = 00 sc[i] = 00 if ((yr[i] == 1900) & (mo[i] == 2) & (dy[i] == 29)): timeobj[i] = nt.datetime(yr[i], 3, 1, hr[i], mi[i], sc[i]) else: timeobj[i] = nt.datetime(yr[i], mo[i], dy[i], hr[i], mi[i], sc[i]) if eng is not None: islist = type(eng) != type(np.array(eng)) isarr = np.ndim(eng) if isarr == 0: eng = np.array([eng]) else: eng = np.array(eng) if (islist & (isarr > 2)): raise ValueError( "date2dec error: eng input is list > 2D; Use array input") eng = np.array(eng) insize = eng.size outsize = insize outshape = eng.shape engfl = eng.flatten() timeobj = np.zeros(insize, dtype=object) # slicing of eng strings to implement in datetime object. missing times # will be set to 00. yr = np.zeros(insize, dtype=np.int) mo = np.zeros(insize, dtype=np.int) dy = np.zeros(insize, dtype=np.int) hr = np.zeros(insize, dtype=np.int) mi = np.zeros(insize, dtype=np.int) sc = np.zeros(insize, dtype=np.int) for i in range(insize): ee = engfl[i].split('-') yr[i] = int(ee[0]) mo[i] = int(ee[1]) tail = ee[2].split() dy[i] = int(tail[0]) if len(tail) > 1: tim = tail[1].split(':') hr[i] = int(tim[0]) if len(tim) > 1: mi[i] = int(tim[1]) else: mi[i] = 00 if len(tim) > 2: sc[i] = int(tim[2]) else: sc[i] = 00 else: hr[i] = 00 mi[i] = 00 sc[i] = 00 if ((yr[i] == 1900) & (mo[i] == 2) & (dy[i] == 29)): timeobj[i] = nt.datetime(yr[i], 3, 1, hr[i], mi[i], sc[i]) else: timeobj[i] = nt.datetime(yr[i], mo[i], dy[i], hr[i], mi[i], sc[i]) # if no ascii input, other inputs will be concidered # calculation of input sizes, shapes and number of axis if ((ascii is None) and (eng is None)): isnlist1 = type(yr) == type(np.array(yr)) isarr1 = np.ndim(yr) if isarr1 == 0: yr = np.array([yr]) else: yr = np.array(yr) isnlist2 = type(mo) == type(np.array(mo)) isarr2 = np.ndim(mo) if isarr2 == 0: mo = np.array([mo]) else: mo = np.array(mo) isnlist3 = type(dy) == type(np.array(dy)) isarr3 = np.ndim(dy) if isarr3 == 0: dy = np.array([dy]) else: dy = np.array(dy) isnlist4 = type(hr) == type(np.array(hr)) isarr4 = np.ndim(hr) if isarr4 == 0: hr = np.array([hr]) else: hr = np.array(hr) isnlist5 = type(mi) == type(np.array(mi)) isarr5 = np.ndim(mi) if isarr5 == 0: mi = np.array([mi]) else: mi = np.array(mi) isnlist6 = type(sc) == type(np.array(sc)) isarr6 = np.ndim(sc) if isarr6 == 0: sc = np.array([sc]) else: sc = np.array(sc) islist = not (isnlist1 | isnlist2 | isnlist3 | isnlist4 | isnlist5 | isnlist6) isarr = isarr1 + isarr2 + isarr3 + isarr4 + isarr5 + isarr6 shapes = [ np.shape(yr), np.shape(mo), np.shape(dy), np.shape(hr), np.shape(mi), np.shape(sc) ] nyr = np.size(yr) nmo = np.size(mo) ndy = np.size(dy) nhr = np.size(hr) nmi = np.size(mi) nsc = np.size(sc) sizes = [nyr, nmo, ndy, nhr, nmi, nsc] nmax = np.amax(sizes) ii = np.argmax(sizes) outshape = shapes[ii] if (islist & (np.size(outshape) > 2)): raise ValueError( "date2dec error: input is list > 2D; Use array input.") if nyr < nmax: if nyr == 1: yr = np.ones(outshape, ) * yr else: raise ValueError( "date2dec error: size of yr != max input or 1.") if nmo < nmax: if nmo == 1: mo = np.ones(outshape) * mo else: raise ValueError( "date2dec error: size of mo != max input or 1.") if ndy < nmax: if ndy == 1: dy = np.ones(outshape) * dy else: raise ValueError( "date2dec error: size of dy != max input or 1.") if nhr < nmax: if nhr == 1: hr = np.ones(outshape) * hr else: raise ValueError( "date2dec error: size of hr != max input or 1.") if nmi < nmax: if nmi == 1: mi = np.ones(outshape) * mi else: raise ValueError( "date2dec error: size of mi != max input or 1.") if nsc < nmax: if nsc == 1: sc = np.ones(outshape) * sc else: raise ValueError( "date2dec error: size of sc != max input or 1.") indate = [yr, mo, dy, hr, mi, sc] insize = [np.size(i) for i in indate] inshape = [np.shape(i) for i in indate] dimnum = [len(i) for i in inshape] # calculation of maximum input size and maximum number of axis for # reshaping the output indate = [i.flatten() for i in indate] outsize = max(insize) timeobj = np.zeros(outsize, dtype=object) # datetime object is constructed for i in range(outsize): iyr = int(indate[0][i]) imo = int(indate[1][i]) idy = int(indate[2][i]) ihr = int(indate[3][i]) imi = int(indate[4][i]) isc = int(indate[5][i]) if ((iyr == 1900) & (imo == 2) & (idy == 29)): timeobj[i] = nt.datetime(iyr, 3, 1, ihr, imi, isc) else: timeobj[i] = nt.datetime(iyr, imo, idy, ihr, imi, isc) # depending on chosen calendar and optional set of the time units # decimal date is calculated output = np.zeros(outsize) t0 = nt.datetime(1582, 10, 05, 00, 00, 00) t1 = nt.datetime(1582, 10, 15, 00, 00, 00) is121 = True if (min(timeobj) < t0) and (max(timeobj) >= t1) else False if (calendar == 'standard') or (calendar == 'gregorian'): if units is None: units = 'days since 0001-01-01 12:00:00' dec0 = 1721424 else: dec0 = 0 if is121 and (nt.__version__ < '1.2.2'): for ii, tt in enumerate(timeobj): output[ii] = nt.date2num(tt, units, calendar='gregorian') + dec0 else: output = nt.date2num(timeobj, units, calendar='gregorian') + dec0 elif calendar == 'julian': if units is None: units = 'days since 0001-01-01 12:00:00' dec0 = 1721424 else: dec0 = 0 if is121 and (nt.__version__ < '1.2.2'): for ii, tt in enumerate(timeobj): output[ii] = nt.date2num(tt, units, calendar='julian') + dec0 else: output = nt.date2num(timeobj, units, calendar='julian') + dec0 elif calendar == 'proleptic_gregorian': if units is None: units = 'days since 0001-01-01 00:00:00' if is121 and (nt.__version__ < '1.2.2'): for ii, tt in enumerate(timeobj): output[ii] = nt.date2num(tt, units, calendar='proleptic_gregorian') else: output = nt.date2num(timeobj, units, calendar='proleptic_gregorian') elif calendar == 'excel1900': doerr = False if units is None: units = 'days since 1899-12-31 00:00:00' if excelerr: doerr = True if is121 and (nt.__version__ < '1.2.2'): for ii, tt in enumerate(timeobj): output[ii] = nt.date2num(tt, units, calendar='gregorian') else: output = nt.date2num(timeobj, units, calendar='gregorian') if doerr: output = np.where(output >= 60., output + 1., output) # date2num treats 29.02.1900 as 01.03.1990, i.e. is the same decimal number if np.any((output >= 61.) & (output < 62.)): for i in range(outsize): # if (timeobj[i].year==1900) & (timeobj[i].month==2) & (timeobj[i].day==29): # output[i] -= 1. if (yr[i] == 1900) & (mo[i] == 2) & (dy[i] == 29): output[i] -= 1. elif calendar == 'excel1904': if units is None: units = 'days since 1903-12-31 00:00:00' if is121 and (nt.__version__ < '1.2.2'): for ii, tt in enumerate(timeobj): output[ii] = nt.date2num(tt, units, calendar='gregorian') else: output = nt.date2num(timeobj, units, calendar='gregorian') elif (calendar == '365_day') or (calendar == 'noleap'): if units is None: units = 'days since 0001-01-01 00:00:00' if is121 and (nt.__version__ < '1.2.2'): for ii, tt in enumerate(timeobj): output[ii] = nt.date2num(tt, units, calendar='365_day') else: output = nt.date2num(timeobj, units, calendar='365_day') elif (calendar == '366_day') or (calendar == 'all_leap'): if units is None: units = 'days since 0001-01-01 00:00:00' if is121 and (nt.__version__ < '1.2.2'): for ii, tt in enumerate(timeobj): output[ii] = nt.date2num(tt, units, calendar='366_day') else: output = nt.date2num(timeobj, units, calendar='366_day') elif calendar == '360_day': if units is None: units = 'days since 0001-01-01 00:00:00' if is121 and (nt.__version__ < '1.2.2'): for ii, tt in enumerate(timeobj): output[ii] = nt.date2num(tt, units, calendar='360_day') else: output = nt.date2num(timeobj, units, calendar='360_day') elif calendar == 'decimal': ntime = np.size(yr) leap = np.array((((yr % 4) == 0) & ((yr % 100) != 0)) | ((yr % 400) == 0)) tdy = np.array(dy, dtype=np.float) diy = np.array( [[-9, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365], [-9, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]]) for i in range(ntime): tdy[i] = tdy[i] + np.array(diy[leap[i], mo[i]], dtype=np.float) days_year = 365. output = (np.array(yr, dtype=np.float) + ((tdy - 1.) * 24. + np.array(hr, dtype=np.float) + np.array(mi, dtype=np.float) / 60. + np.array(sc, dtype=np.float) / 3600.) / ((days_year + np.array(leap, dtype=np.float)) * 24.)) # for numerical stability, i.e. back and forth transforms output += 1e-08 # 1/3 sec elif calendar == 'decimal360': ntime = np.size(yr) tdy = np.array(dy, dtype=np.float) diy = np.array( [-9, 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360]) for i in range(ntime): tdy[i] = tdy[i] + np.array(diy[mo[i]], dtype=np.float) days_year = 360. output = (np.array(yr, dtype=np.float) + ((tdy - 1.) * 24. + np.array(hr, dtype=np.float) + np.array(mi, dtype=np.float) / 60. + np.array(sc, dtype=np.float) / 3600.) / (days_year * 24.)) # for numerical stability, i.e. back and forth transforms output += 1e-08 # 1/3 sec else: raise ValueError( "date2dec error: calendar not implemented; should have been catched before." ) # return of reshaped output output = np.reshape(output, outshape) if isarr == 0: output = np.float(output) else: if islist: ns = np.size(outshape) if ns == 1: output = [i for i in output] else: loutput = [i for i in output[:, 0]] for i in range(np.size(output[:, 0])): loutput[i] = list(np.squeeze(output[i, :])) output = loutput return output
def fill(self,data,tind='next',quiet=1): ''' Fills model netcdf bulk forcing file ''' nc=netcdf.Pync(self.filename,'w') if tind=='next': tind=nc.dims['time'] if not quiet: print 'filling blk file %s' % self.filename # about time: try: date=dts.parse_date(data['date']) time=netcdftime.date2num(date,self.tunits) except: time=data['date'] # date as number! for i in nc.varnames: if i.endswith('time'): if not quiet: print ' -- %s tind=%d %f' % (i,tind,time) nc.vars[i][tind]=time if 'Tair' in nc.varnames: # roms names=('Tair','tair'),('Pair','pres'),('Qair','rhum'),('rain','prate'),\ ('swrad','radsw'),('lwrad','radlw'),('Uwind','uwnd'),('Vwind','vwnd'),\ 'sustr','svstr','wspd','cloud' if not 'tair' in data.keys(): # assuming data has roms (not agrif) varnames: names='Tair','Pair','Qair','rain','swrad','lwrad','Uwind','Vwind','sustr','svstr','wspd','cloud' elif 'tair' in nc.varnames: # roms-agrif names='tair','pres','rhum','prate','radlw','radsw','dlwrf','uwnd',\ 'vwnd','wspd','sustr','svstr',\ 'cloud' # not used, but add it anyway for i in names: if isinstance(i,basestring): filev,datav=i,i else: filev,datav=i if datav not in data.keys(): if not quiet: print ' Warning: data key %s not present' % datav else: if not quiet: print ' %s (%s) min=%8.3f max=%8.3f' % (filev.ljust(7),datav.ljust(7), data[datav].min(),data[datav].max()) nc.vars[filev][tind,...]=data[datav] # fill original data: orig=datav+'_original' if orig in data.keys() and not orig in nc.varnames: if not quiet: print ' Warning: original data will not be written %s' % orig elif not orig in data.keys() and orig in nc.varnames: if not quiet: print ' Warning: original data not present %s' % orig elif orig in data.keys() and orig in nc.varnames: if not quiet: print ' %s min=%8.3f max=%8.3f' % (orig.ljust(7+9), data[orig].min(),data[orig].max()) nc.vars[orig][tind,...]=data[orig] # fill original x,y: if tind==0 and 'x_original' in data.keys() and 'x_original' in nc.varnames: if not quiet: print ' filling x,y original' nc.vars['x_original'][:]=data['x_original'] nc.vars['y_original'][:]=data['y_original'] nc.close()
def write_combined_data_netcdf(data, stationid, lon, lat, elevation): ''' description ''' from netCDF4 import Dataset as ncdf import netcdftime from datetime import datetime from dateutil import tz from numpy import zeros from numpy import nan as npnan from numpy import dtype import time ncfile = ncdf('output'+str(stationid)+'.nc', 'w', format='NETCDF4') # description of the file ncfile.description = 'KNMI ' + str(stationid) ncfile.history = 'Created ' + time.ctime(time.time()) # create time dimension timevar = ncfile.createDimension('time', None) # create lon/lat dimensions lonvar = ncfile.createDimension('longitude', 1) latvar = ncfile.createDimension('latitude', 1) # elevation elvar = ncfile.createDimension('elevation', 1) # inititalize time axis timeaxis = [int(round(netcdftime.date2num(data['datetime'][idx], units='minutes since 2010-01-01 00:00:00', calendar='gregorian'))) for idx in range(0,len(data['datetime']))] # netcdf time variable UTC timevar = ncfile.createVariable('time', 'i4', ('time',), zlib=True) timevar[:] = timeaxis timevar.units = 'minutes since 2010-01-01 00:00:00' timevar.calendar = 'gregorian' timevar.standard_name = 'time' timevar.long_name = 'time in UTC' # lon/lat variables lonvar = ncfile.createVariable('longitude',dtype('float32').char,('longitude',)) lonvar.units = 'degrees_east' lonvar.axis = 'X' lonvar.standard_name = 'longitude' lonvar[:] = lon latvar = ncfile.createVariable('latitude',dtype('float32').char,('latitude',)) latvar.units = 'degrees_north' latvar.axis = 'Y' latvar.standard_name = 'latitude' latvar[:] = lat # elevation variable elvar = ncfile.createVariable('elevation', dtype('float32').char, ('elevation',)) elvar.units = 'meter' elvar.axis = 'Z' elvar.standard_name = 'elevation' elvar[:] = elevation # create other variables in netcdf file for variable in data.keys(): if variable not in ['YYYMMDD', 'Time', '<br>', 'datetime', '# STN', None]: # add variables in netcdf file # convert strings to npnan if array contains numbers if True in [is_number(c) for c in data[variable]]: data[variable] = [npnan if isinstance( fitem(c), str) else fitem(c) for c in data[ variable]] # check if variable is a string if not isinstance(data[variable][1], str): # fill variable variableName = variable values = ncfile.createVariable( variableName, type(data[variable][1]), ('time',), zlib=True, fill_value=-999) else: # string variables cannot have fill_value values = ncfile.createVariable( variable, type(data[variable][1]), ('time',), zlib=True) try: # fill variable values[:] = data[variable][:] except IndexError: # for strings the syntax is slightly different values = data[variable][:]
def torelative(self, units, calendar=None): if calendar is None: calendar = StandardCalendar t = nct.date2num(self._datetime, units, calendar=_calendar_map[calendar]) return RelTime(t, units)
def runTest(self): """testing netcdftime""" # test mixed julian/gregorian calendar # check attributes. self.assertTrue(self.cdftime_mixed.units == 'hours') self.assertTrue( repr(self.cdftime_mixed.origin) == ' 1-01-01 00:00:00') self.assertTrue( self.cdftime_mixed.unit_string == 'hours since 0001-01-01 00:00:00') self.assertTrue(self.cdftime_mixed.calendar == 'standard') # check date2num method. (date before switch) d = datetime(1582, 10, 4, 23) t1 = self.cdftime_mixed.date2num(d) assert_almost_equal(t1, 13865687.0) # check num2date method. d2 = self.cdftime_mixed.num2date(t1) self.assertTrue(str(d) == str(d2)) # this is a non-existant date, should raise ValueError. d = datetime(1582, 10, 5, 0) self.assertRaises(ValueError, self.cdftime_mixed.date2num, d) # check date2num/num2date with date after switch. d = datetime(1582, 10, 15, 0) t2 = self.cdftime_mixed.date2num(d) assert_almost_equal(t2, 13865688.0) d2 = self.cdftime_mixed.num2date(t2) self.assertTrue(str(d) == str(d2)) # check day of year. ndayr = d.timetuple()[7] self.assertTrue(ndayr == 288) # test using numpy arrays. t = numpy.arange(t2, t2 + 240.0, 12.) t = numpy.reshape(t, (4, 5)) d = self.cdftime_mixed.num2date(t) self.assertTrue(d.shape == t.shape) d_check = "1582-10-15 00:00:001582-10-15 12:00:001582-10-16 00:00:001582-10-16 12:00:001582-10-17 00:00:001582-10-17 12:00:001582-10-18 00:00:001582-10-18 12:00:001582-10-19 00:00:001582-10-19 12:00:001582-10-20 00:00:001582-10-20 12:00:001582-10-21 00:00:001582-10-21 12:00:001582-10-22 00:00:001582-10-22 12:00:001582-10-23 00:00:001582-10-23 12:00:001582-10-24 00:00:001582-10-24 12:00:00" d2 = [str(dd) for dd in d.flat] self.assertTrue(d_check == ''.join(d2)) # test julian calendar with numpy arrays d = self.cdftime_julian.num2date(t) self.assertTrue(d.shape == t.shape) d_check = "1582-10-05 00:00:001582-10-05 12:00:001582-10-06 00:00:001582-10-06 12:00:001582-10-07 00:00:001582-10-07 12:00:001582-10-08 00:00:001582-10-08 12:00:001582-10-09 00:00:001582-10-09 12:00:001582-10-10 00:00:001582-10-10 12:00:001582-10-11 00:00:001582-10-11 12:00:001582-10-12 00:00:001582-10-12 12:00:001582-10-13 00:00:001582-10-13 12:00:001582-10-14 00:00:001582-10-14 12:00:00" d2 = [str(dd) for dd in d.flat] self.assertTrue(d_check == ''.join(d2)) # test proleptic gregorian calendar. self.assertTrue(self.cdftime_pg.units == 'seconds') self.assertTrue(repr(self.cdftime_pg.origin) == ' 1-01-01 00:00:00') self.assertTrue( self.cdftime_pg.unit_string == 'seconds since 0001-01-01 00:00:00') self.assertTrue(self.cdftime_pg.calendar == 'proleptic_gregorian') # check date2num method. d = datetime(1990, 5, 5, 2, 17) t1 = numpy.around(self.cdftime_pg.date2num(d)) self.assertTrue(t1 == 62777470620.0) # check num2date method. d2 = self.cdftime_pg.num2date(t1) self.assertTrue(str(d) == str(d2)) # check day of year. ndayr = d.timetuple()[7] self.assertTrue(ndayr == 125) # check noleap calendar. # this is a non-existant date, should raise ValueError. self.assertRaises( ValueError, utime, 'days since 1600-02-29 00:00:00', calendar='noleap') self.assertTrue(self.cdftime_noleap.units == 'days') self.assertTrue( repr(self.cdftime_noleap.origin) == '1600-02-28 00:00:00') self.assertTrue( self.cdftime_noleap.unit_string == 'days since 1600-02-28 00:00:00') self.assertTrue(self.cdftime_noleap.calendar == 'noleap') assert_almost_equal( self.cdftime_noleap.date2num(self.cdftime_noleap.origin), 0.0) # check date2num method. d1 = datetime(2000, 2, 28) d2 = datetime(1600, 2, 28) t1 = self.cdftime_noleap.date2num(d1) t2 = self.cdftime_noleap.date2num(d2) assert_almost_equal(t1, 400 * 365.) assert_almost_equal(t2, 0.) t12 = self.cdftime_noleap.date2num([d1, d2]) assert_almost_equal(t12, [400 * 365., 0]) # check num2date method. d2 = self.cdftime_noleap.num2date(t1) self.assertTrue(str(d1) == str(d2)) # check day of year. ndayr = d2.timetuple()[7] self.assertTrue(ndayr == 59) # non-existant date, should raise ValueError. date = datetime(2000, 2, 29) self.assertRaises(ValueError, self.cdftime_noleap.date2num, date) # check all_leap calendar. self.assertTrue(self.cdftime_leap.units == 'days') self.assertTrue( repr(self.cdftime_leap.origin) == '1600-02-29 00:00:00') self.assertTrue( self.cdftime_leap.unit_string == 'days since 1600-02-29 00:00:00') self.assertTrue(self.cdftime_leap.calendar == 'all_leap') assert_almost_equal( self.cdftime_leap.date2num(self.cdftime_leap.origin), 0.0) # check date2num method. d1 = datetime(2000, 2, 29) d2 = datetime(1600, 2, 29) t1 = self.cdftime_leap.date2num(d1) t2 = self.cdftime_leap.date2num(d2) assert_almost_equal(t1, 400 * 366.) assert_almost_equal(t2, 0.) # check num2date method. d2 = self.cdftime_leap.num2date(t1) self.assertTrue(str(d1) == str(d2)) # check day of year. ndayr = d2.timetuple()[7] self.assertTrue(ndayr == 60) # double check date2num,num2date methods. d = datetime(2000, 12, 31) t1 = self.cdftime_mixed.date2num(d) d2 = self.cdftime_mixed.num2date(t1) self.assertTrue(str(d) == str(d2)) ndayr = d2.timetuple()[7] self.assertTrue(ndayr == 366) # check 360_day calendar. self.assertTrue(self.cdftime_360day.units == 'days') self.assertTrue( repr(self.cdftime_360day.origin) == '1600-02-30 00:00:00') self.assertTrue( self.cdftime_360day.unit_string == 'days since 1600-02-30 00:00:00') self.assertTrue(self.cdftime_360day.calendar == '360_day') assert_almost_equal( self.cdftime_360day.date2num(self.cdftime_360day.origin), 0.0) # check date2num,num2date methods. # use datetime from netcdftime, since this date doesn't # exist in "normal" calendars. d = datetimex(2000, 2, 30) t1 = self.cdftime_360day.date2num(d) assert_almost_equal(t1, 360 * 400.) d2 = self.cdftime_360day.num2date(t1) assert_equal(str(d), str(d2)) # check day of year. d = datetime(2001, 12, 30) t = self.cdftime_360day.date2num(d) assert_almost_equal(t, 144660.0) date = self.cdftime_360day.num2date(t) self.assertTrue(str(d) == str(date)) ndayr = date.timetuple()[7] self.assertTrue(ndayr == 360) # Check fraction d = datetime(1969, 12, 30, 12) t = self.cdftime_360day.date2num(d) date = self.cdftime_360day.num2date(t) assert_equal(str(d), str(date)) # test proleptic julian calendar. d = datetime(1858, 11, 17, 12) t = self.cdftime_jul.date2num(d) assert_almost_equal(t, 7528932.0) d1 = datetime(1582, 10, 4, 23) d2 = datetime(1582, 10, 15, 0) assert_almost_equal( self.cdftime_jul.date2num(d1) + 241.0, self.cdftime_jul.date2num(d2)) date = self.cdftime_jul.num2date(t) self.assertTrue(str(d) == str(date)) # test julian day from date, date from julian day d = datetime(1858, 11, 17) mjd = JulianDayFromDate(d) assert_almost_equal(mjd, 2400000.5) date = DateFromJulianDay(mjd) self.assertTrue(str(date) == str(d)) # test iso 8601 units string d = datetime(1970, 1, 1, 1) t = self.cdftime_iso.date2num(d) assert_equal(numpy.around(t), 3600) # test fix for issue 75 (seconds hit 60 at end of month, # day goes out of range). t = 733498.999999 d = num2date(t, units='days since 0001-01-01 00:00:00') assert_equal(str(d), '2009-04-01 00:00:00') # test edge case of issue 75 for numerical problems for t in (733498.999, 733498.9999, 733498.99999, 733498.999999, 733498.9999999): d = num2date(t, units='days since 0001-01-01 00:00:00') t2 = date2num(d, units='days since 0001-01-01 00:00:00') assert(abs(t2 - t) < 1e-5) # values should be less than second # Check equality testing d1 = datetimex(1979, 6, 21, 9, 23, 12) d2 = datetime(1979, 6, 21, 9, 23, 12) assert(d1 == d2) # check timezone offset d = datetime(2012, 2, 29, 15) assert(self.cdftime_mixed.date2num( d) - self.cdftime_mixed_tz.date2num(d) == 6) # Check comparisons with Python datetime types d1 = num2date(0, 'days since 1000-01-01', 'standard') d2 = datetime(2000, 1, 1) d3 = num2date(0, 'days since 3000-01-01', 'standard') assert d1 < d2 assert d2 < d3 # check all comparisons assert d1 != d2 assert d1 <= d2 assert d2 > d1 assert d2 >= d1 # check datetime hash d1 = datetimex(1995, 1, 1) d2 = datetime(1995, 1, 1) d3 = datetimex(2001, 2, 30) assert hash(d1) == hash(d1) assert hash(d1) == hash(d2) assert hash(d1) != hash(d3) assert hash(d3) == hash(d3) # check datetime immutability with self.assertRaises(AttributeError): d1.year = 1999 with self.assertRaises(AttributeError): d1.month = 6 with self.assertRaises(AttributeError): d1.day = 5 with self.assertRaises(AttributeError): d1.hour = 10 with self.assertRaises(AttributeError): d1.minute = 33 with self.assertRaises(AttributeError): d1.second = 45 with self.assertRaises(AttributeError): d1.dayofwk = 1 with self.assertRaises(AttributeError): d1.dayofyr = 52 with self.assertRaises(AttributeError): d1.format = '%Y' # Check leading white space self.assertEqual( repr(self.cdftime_leading_space.origin), ' 850-01-01 00:00:00') #issue 330 units = "seconds since 1970-01-01T00:00:00Z" t = utime(units) for n in range(10): assert n == int(round(t.date2num(t.num2date(n))))
def runTest(self): """testing netcdftime""" # test mixed julian/gregorian calendar # check attributes. self.assertTrue(self.cdftime_mixed.units == 'hours') self.assertTrue( str(self.cdftime_mixed.origin) == ' 1-01-01 00:00:00') self.assertTrue(self.cdftime_mixed.unit_string == 'hours since 0001-01-01 00:00:00') self.assertTrue(self.cdftime_mixed.calendar == 'standard') # check date2num method. (date before switch) d = datetime(1582, 10, 4, 23) t1 = self.cdftime_mixed.date2num(d) assert_almost_equal(t1, 13865687.0) # check num2date method. d2 = self.cdftime_mixed.num2date(t1) self.assertTrue(str(d) == str(d2)) # this is a non-existant date, should raise ValueError. d = datetime(1582, 10, 5, 0) self.assertRaises(ValueError, self.cdftime_mixed.date2num, d) # check date2num/num2date with date after switch. d = datetime(1582, 10, 15, 0) t2 = self.cdftime_mixed.date2num(d) assert_almost_equal(t2, 13865688.0) d2 = self.cdftime_mixed.num2date(t2) self.assertTrue(str(d) == str(d2)) # check day of year. ndayr = d.timetuple()[7] self.assertTrue(ndayr == 288) # test using numpy arrays. t = numpy.arange(t2, t2 + 240.0, 12.) t = numpy.reshape(t, (4, 5)) d = self.cdftime_mixed.num2date(t) self.assertTrue(d.shape == t.shape) d_check = "1582-10-15 00:00:001582-10-15 12:00:001582-10-16 00:00:001582-10-16 12:00:001582-10-17 00:00:001582-10-17 12:00:001582-10-18 00:00:001582-10-18 12:00:001582-10-19 00:00:001582-10-19 12:00:001582-10-20 00:00:001582-10-20 12:00:001582-10-21 00:00:001582-10-21 12:00:001582-10-22 00:00:001582-10-22 12:00:001582-10-23 00:00:001582-10-23 12:00:001582-10-24 00:00:001582-10-24 12:00:00" d2 = [str(dd) for dd in d.flat] self.assertTrue(d_check == ''.join(d2)) # test julian calendar with numpy arrays d = self.cdftime_julian.num2date(t) self.assertTrue(d.shape == t.shape) d_check = "1582-10-05 00:00:001582-10-05 12:00:001582-10-06 00:00:001582-10-06 12:00:001582-10-07 00:00:001582-10-07 12:00:001582-10-08 00:00:001582-10-08 12:00:001582-10-09 00:00:001582-10-09 12:00:001582-10-10 00:00:001582-10-10 12:00:001582-10-11 00:00:001582-10-11 12:00:001582-10-12 00:00:001582-10-12 12:00:001582-10-13 00:00:001582-10-13 12:00:001582-10-14 00:00:001582-10-14 12:00:00" d2 = [str(dd) for dd in d.flat] self.assertTrue(d_check == ''.join(d2)) # test proleptic gregorian calendar. self.assertTrue(self.cdftime_pg.units == 'seconds') self.assertTrue(str(self.cdftime_pg.origin) == ' 1-01-01 00:00:00') self.assertTrue( self.cdftime_pg.unit_string == 'seconds since 0001-01-01 00:00:00') self.assertTrue(self.cdftime_pg.calendar == 'proleptic_gregorian') # check date2num method. d = datetime(1990, 5, 5, 2, 17) t1 = numpy.around(self.cdftime_pg.date2num(d)) self.assertTrue(t1 == 62777470620.0) # check num2date method. d2 = self.cdftime_pg.num2date(t1) self.assertTrue(str(d) == str(d2)) # check day of year. ndayr = d.timetuple()[7] self.assertTrue(ndayr == 125) # check noleap calendar. # this is a non-existant date, should raise ValueError. self.assertRaises(ValueError, utime, 'days since 1600-02-29 00:00:00', calendar='noleap') self.assertTrue(self.cdftime_noleap.units == 'days') self.assertTrue( str(self.cdftime_noleap.origin) == '1600-02-28 00:00:00') self.assertTrue(self.cdftime_noleap.unit_string == 'days since 1600-02-28 00:00:00') self.assertTrue(self.cdftime_noleap.calendar == 'noleap') assert_almost_equal( self.cdftime_noleap.date2num(self.cdftime_noleap.origin), 0.0) # check date2num method. d1 = datetime(2000, 2, 28) d2 = datetime(1600, 2, 28) t1 = self.cdftime_noleap.date2num(d1) t2 = self.cdftime_noleap.date2num(d2) assert_almost_equal(t1, 400 * 365.) assert_almost_equal(t2, 0.) t12 = self.cdftime_noleap.date2num([d1, d2]) assert_almost_equal(t12, [400 * 365., 0]) # check num2date method. d2 = self.cdftime_noleap.num2date(t1) self.assertTrue(str(d1) == str(d2)) # check day of year. ndayr = d2.timetuple()[7] self.assertTrue(ndayr == 59) # non-existant date, should raise ValueError. date = datetime(2000, 2, 29) self.assertRaises(ValueError, self.cdftime_noleap.date2num, date) # check all_leap calendar. self.assertTrue(self.cdftime_leap.units == 'days') self.assertTrue(str(self.cdftime_leap.origin) == '1600-02-29 00:00:00') self.assertTrue( self.cdftime_leap.unit_string == 'days since 1600-02-29 00:00:00') self.assertTrue(self.cdftime_leap.calendar == 'all_leap') assert_almost_equal( self.cdftime_leap.date2num(self.cdftime_leap.origin), 0.0) # check date2num method. d1 = datetime(2000, 2, 29) d2 = datetime(1600, 2, 29) t1 = self.cdftime_leap.date2num(d1) t2 = self.cdftime_leap.date2num(d2) assert_almost_equal(t1, 400 * 366.) assert_almost_equal(t2, 0.) # check num2date method. d2 = self.cdftime_leap.num2date(t1) self.assertTrue(str(d1) == str(d2)) # check day of year. ndayr = d2.timetuple()[7] self.assertTrue(ndayr == 60) # double check date2num,num2date methods. d = datetime(2000, 12, 31) t1 = self.cdftime_mixed.date2num(d) d2 = self.cdftime_mixed.num2date(t1) self.assertTrue(str(d) == str(d2)) ndayr = d2.timetuple()[7] self.assertTrue(ndayr == 366) # check 360_day calendar. self.assertTrue(self.cdftime_360day.units == 'days') self.assertTrue( str(self.cdftime_360day.origin) == '1600-02-30 00:00:00') self.assertTrue(self.cdftime_360day.unit_string == 'days since 1600-02-30 00:00:00') self.assertTrue(self.cdftime_360day.calendar == '360_day') assert_almost_equal( self.cdftime_360day.date2num(self.cdftime_360day.origin), 0.0) # check date2num,num2date methods. # use datetime from netcdftime, since this date doesn't # exist in "normal" calendars. d = datetimex(2000, 2, 30) t1 = self.cdftime_360day.date2num(d) assert_almost_equal(t1, 360 * 400.) d2 = self.cdftime_360day.num2date(t1) assert_equal(str(d), str(d2)) # check day of year. d = datetime(2001, 12, 30) t = self.cdftime_360day.date2num(d) assert_almost_equal(t, 144660.0) date = self.cdftime_360day.num2date(t) self.assertTrue(str(d) == str(date)) ndayr = date.timetuple()[7] self.assertTrue(ndayr == 360) # Check fraction d = datetime(1969, 12, 30, 12) t = self.cdftime_360day.date2num(d) date = self.cdftime_360day.num2date(t) assert_equal(str(d), str(date)) # test proleptic julian calendar. d = datetime(1858, 11, 17, 12) t = self.cdftime_jul.date2num(d) assert_almost_equal(t, 7528932.0) d1 = datetime(1582, 10, 4, 23) d2 = datetime(1582, 10, 15, 0) assert_almost_equal( self.cdftime_jul.date2num(d1) + 241.0, self.cdftime_jul.date2num(d2)) date = self.cdftime_jul.num2date(t) self.assertTrue(str(d) == str(date)) # test julian day from date, date from julian day d = datetime(1858, 11, 17) mjd = JulianDayFromDate(d) assert_almost_equal(mjd, 2400000.5) date = DateFromJulianDay(mjd) self.assertTrue(str(date) == str(d)) # test iso 8601 units string d = datetime(1970, 1, 1, 1) t = self.cdftime_iso.date2num(d) assert_equal(numpy.around(t), 3600) # test fix for issue 75 (seconds hit 60 at end of month, # day goes out of range). t = 733499.0 d = num2date(t, units='days since 0001-01-01 00:00:00') dateformat = '%Y-%m-%d %H:%M:%S' assert_equal(d.strftime(dateformat), '2009-04-01 00:00:00') # test edge case of issue 75 for numerical problems for t in (733498.999, 733498.9999, 733498.99999, 733498.999999, 733498.9999999): d = num2date(t, units='days since 0001-01-01 00:00:00') t2 = date2num(d, units='days since 0001-01-01 00:00:00') assert (abs(t2 - t) < 1e-5) # values should be less than second # Check equality testing d1 = datetimex(1979, 6, 21, 9, 23, 12) d2 = datetime(1979, 6, 21, 9, 23, 12) assert (d1 == d2) # check timezone offset d = datetime(2012, 2, 29, 15) # mixed_tz is -6 hours from UTC, mixed is UTC so # difference in elapsed time is 6 hours. assert (self.cdftime_mixed_tz.date2num(d) - self.cdftime_mixed.date2num(d) == 6) # Check comparisons with Python datetime types # Note that d1 has to use the proleptic Gregorian calendar to # be comparable to d2: datetime.datetime uses the proleptic # Gregorian calendar and year 1000 is before the # Julian/Gregorian transition (1582-10-15). d1 = num2date(0, 'days since 1000-01-01', 'proleptic_gregorian') d2 = datetime(2000, 1, 1) # The date d3 is well after the Julian/Gregorian transition # and so this Gregorian date can be compared to the proleptic # Gregorian date d2. d3 = num2date(0, 'days since 3000-01-01', 'standard') assert d1 < d2 assert d2 < d3 # check all comparisons assert d1 != d2 assert d1 <= d2 assert d2 > d1 assert d2 >= d1 # check datetime hash d1 = datetimex(1995, 1, 1) d2 = datetime(1995, 1, 1) d3 = datetimex(2001, 2, 30) assert hash(d1) == hash(d1) assert hash(d1) == hash(d2) assert hash(d1) != hash(d3) assert hash(d3) == hash(d3) # check datetime immutability # using assertRaises as a context manager # only works with python >= 2.7 (issue #497). immutability_tests = { "year": 1999, "month": 6, "day": 5, "hour": 10, "minute": 33, "second": 45, "dayofwk": 1, "dayofyr": 52, "format": '%Y' } for name, value in immutability_tests.items(): self.assertRaises(AttributeError, setattr, d1, name, value) # Check leading white space self.assertEqual(str(self.cdftime_leading_space.origin), ' 850-01-01 00:00:00') #issue 330 units = "seconds since 1970-01-01T00:00:00Z" t = utime(units) for n in range(10): assert n == int(round(t.date2num(t.num2date(n)))) #issue 344 units = 'hours since 2013-12-12T12:00:00' assert (1.0 == date2num(num2date(1.0, units), units)) # test rountrip accuracy # also tests error found in issue #349 calendars=['standard', 'gregorian', 'proleptic_gregorian', 'noleap', 'julian',\ 'all_leap', '365_day', '366_day', '360_day'] dateformat = '%Y-%m-%d %H:%M:%S' dateref = datetime(2015, 2, 28, 12) ntimes = 1001 for calendar in calendars: eps = 100. units = 'microseconds since 1800-01-30 01:01:01' microsecs1 = date2num(dateref, units, calendar=calendar) for n in range(ntimes): microsecs1 += 1. date1 = num2date(microsecs1, units, calendar=calendar) microsecs2 = date2num(date1, units, calendar=calendar) date2 = num2date(microsecs2, units, calendar=calendar) err = numpy.abs(microsecs1 - microsecs2) assert (err < eps) assert ( date1.strftime(dateformat) == date2.strftime(dateformat)) units = 'milliseconds since 1800-01-30 01:01:01' eps = 0.1 millisecs1 = date2num(dateref, units, calendar=calendar) for n in range(ntimes): millisecs1 += 0.001 date1 = num2date(millisecs1, units, calendar=calendar) millisecs2 = date2num(date1, units, calendar=calendar) date2 = num2date(millisecs2, units, calendar=calendar) err = numpy.abs(millisecs1 - millisecs2) assert (err < eps) assert ( date1.strftime(dateformat) == date2.strftime(dateformat)) eps = 1.e-4 units = 'seconds since 0001-01-30 01:01:01' secs1 = date2num(dateref, units, calendar=calendar) for n in range(ntimes): secs1 += 0.1 date1 = num2date(secs1, units, calendar=calendar) secs2 = date2num(date1, units, calendar=calendar) date2 = num2date(secs2, units, calendar=calendar) err = numpy.abs(secs1 - secs2) assert (err < eps) assert ( date1.strftime(dateformat) == date2.strftime(dateformat)) eps = 1.e-5 units = 'minutes since 0001-01-30 01:01:01' mins1 = date2num(dateref, units, calendar=calendar) for n in range(ntimes): mins1 += 0.01 date1 = num2date(mins1, units, calendar=calendar) mins2 = date2num(date1, units, calendar=calendar) date2 = num2date(mins2, units, calendar=calendar) err = numpy.abs(mins1 - mins2) assert (err < eps) assert ( date1.strftime(dateformat) == date2.strftime(dateformat)) eps = 1.e-5 units = 'hours since 0001-01-30 01:01:01' hrs1 = date2num(dateref, units, calendar=calendar) for n in range(ntimes): hrs1 += 0.001 date1 = num2date(hrs1, units, calendar=calendar) hrs2 = date2num(date1, units, calendar=calendar) date2 = num2date(hrs2, units, calendar=calendar) err = numpy.abs(hrs1 - hrs2) assert (err < eps) assert ( date1.strftime(dateformat) == date2.strftime(dateformat)) eps = 1.e-5 units = 'days since 0001-01-30 01:01:01' days1 = date2num(dateref, units, calendar=calendar) for n in range(ntimes): days1 += 0.00001 date1 = num2date(days1, units, calendar=calendar) days2 = date2num(date1, units, calendar=calendar) date2 = num2date(days2, units, calendar=calendar) err = numpy.abs(days1 - days2) assert (err < eps) assert ( date1.strftime(dateformat) == date2.strftime(dateformat)) # issue 353 assert (num2date(0, 'hours since 2000-01-01 0') == datetime( 2000, 1, 1, 0)) # issue 354 num1 = numpy.array([[0, 1], [2, 3]]) num2 = numpy.array([[0, 1], [2, 3]]) dates1 = num2date(num1, 'days since 0001-01-01') dates2 = num2date(num2, 'days since 2001-01-01') assert (dates1.shape == (2, 2)) assert (dates2.shape == (2, 2)) num1b = date2num(dates1, 'days since 0001-01-01') num2b = date2num(dates2, 'days since 2001-01-01') assert (num1b.shape == (2, 2)) assert (num2b.shape == (2, 2)) assert_almost_equal(num1, num1b) assert_almost_equal(num2, num2b) # issue 357 (make sure time zone offset in units done correctly) # Denver time, 7 hours behind UTC units = 'hours since 1682-10-15 -07:00 UTC' # date after gregorian switch, python datetime used date = datetime(1682, 10, 15) # assumed UTC num = date2num(date, units) # UTC is 7 hours ahead of units, so num should be 7 assert (num == 7) assert (num2date(num, units) == date) units = 'hours since 1482-10-15 -07:00 UTC' # date before gregorian switch, netcdftime datetime used date = datetime(1482, 10, 15) num = date2num(date, units) date2 = num2date(num, units) assert (num == 7) assert (date2.year == date.year) assert (date2.month == date.month) assert (date2.day == date.day) assert (date2.hour == date.hour) assert (date2.minute == date.minute) assert (date2.second == date.second) # issue 362: case insensitive calendars self.assertTrue(self.cdftime_mixed_capcal.calendar == 'standard') self.assertTrue(self.cdftime_noleap_capcal.calendar == 'noleap') d = datetime(2015, 3, 4, 12, 18, 30) units = 'days since 0001-01-01' for cap_cal, low_cal in (('STANDARD', 'standard'), ('NoLeap', 'noleap'), ('Gregorian', 'gregorian'), ('ALL_LEAP', 'all_leap')): d1 = date2num(d, units, cap_cal) d2 = date2num(d, units, low_cal) self.assertEqual(d1, d2) self.assertEqual(num2date(d1, units, cap_cal), num2date(d1, units, low_cal)) # issue 415 t = datetimex(2001, 12, 1, 2, 3, 4) self.assertEqual(t, copy.deepcopy(t)) # issue 442 units = "days since 0000-01-01 00:00:00" # this should fail (year zero not allowed with real-world calendars) try: date2num(datetime(1, 1, 1), units, calendar='standard') except ValueError: pass # this should not fail (year zero allowed in 'fake' calendars) t = date2num(datetime(1, 1, 1), units, calendar='360_day') self.assertEqual(t, 360) d = num2date(t, units, calendar='360_day') self.assertEqual(d, Datetime360Day(1, 1, 1)) d = num2date(0, units, calendar='360_day') self.assertEqual(d, Datetime360Day(0, 1, 1)) # list around missing dates in Gregorian calendar # scalar units = 'days since 0001-01-01 12:00:00' t1 = date2num(datetime(1582, 10, 4), units, calendar='gregorian') t2 = date2num(datetime(1582, 10, 15), units, calendar='gregorian') self.assertEqual(t1 + 1, t2) # list t1, t2 = date2num([datetime(1582, 10, 4), datetime(1582, 10, 15)], units, calendar='gregorian') self.assertEqual(t1 + 1, t2) t1, t2 = date2num([datetime(1582, 10, 4), datetime(1582, 10, 15)], units, calendar='standard') self.assertEqual(t1 + 1, t2) # this should fail: days missing in Gregorian calendar try: t1, t2, t3 = date2num([ datetime(1582, 10, 4), datetime(1582, 10, 10), datetime(1582, 10, 15) ], units, calendar='standard') except ValueError: pass
def frc2gnome(fname,frc,grd,xylim=False,dates=False,ij=(1,1),**kargs): ''' Creates GNOME wind file kargs: t[u,v]var t[u,v]dim x[y,ang]var Ex: .frc2gnome(out,frc,grd,ij=(10,10),dates=dates,**{'tdim':'Time'}) ''' deta,dxi=ij tvar='time' uvar='Uwind' vvar='Vwind' #tvar='bulk_time' #uvar='uwnd' #vvar='vwnd' tdim='time' #tdim='bulk_time' xdim='xi_rho' ydim='eta_rho' xvar='lon_rho' yvar='lat_rho' angvar='angle' if 'tvar' in kargs.keys(): tvar=kargs['tvar'] if 'uvar' in kargs.keys(): uvar=kargs['uvar'] if 'vvar' in kargs.keys(): vvar=kargs['vvar'] if 'tdim' in kargs.keys(): tdim=kargs['tdim'] if 'xdim' in kargs.keys(): xdim=kargs['xdim'] if 'ydim' in kargs.keys(): ydim=kargs['ydim'] if 'xvar' in kargs.keys(): xvar=kargs['xvar'] if 'yvar' in kargs.keys(): yvar=kargs['yvar'] if 'angvar' in kargs.keys(): angvar=kargs['angvar'] dims=netcdf.fdim(grd) xi,eta=dims[xdim],dims[ydim] xi0,eta0=xi,eta ncg=netcdf.ncopen(grd) nc0=netcdf.ncopen(frc) try: t=netcdf.nctime(nc0,tvar) except: t=netcdf.use(nc0,tvar) t=netcdftime.num2date(t,'days since %d-01-01' % year0) time=netcdftime.date2num(t,tunits) x0=netcdf.use(grd,xvar) y0=netcdf.use(grd,yvar) if x0.ndim==1: x0,y0=np.meshgrid(x0,y0) if angvar: ang=netcdf.use(grd,angvar) if not xylim is False: xlim=xylim[:2] ylim=xylim[2:] i1,i2,j1,j2=calc.ij_limits(x0,y0,xlim,ylim) xi=i2-i1 eta=j2-j1 else: i1,i2=0,xi j1,j2=0,eta XI ='%d:%d:%d' %(i1,i2,dxi) ETA ='%d:%d:%d' %(j1,j2,deta) xi=len(range(i1,i2,dxi)) eta=len(range(j1,j2,deta)) # create file: create_wind(fname,xi,eta) nc=netcdf.ncopen(fname,'a') x=x0[j1:j2:deta,i1:i2:dxi] y=y0[j1:j2:deta,i1:i2:dxi] nc.vars['lon'][:]=x nc.vars['lat'][:]=y if angvar: ang=ang[j1:j2:deta,i1:i2:dxi] n=-1 for it in range(len(time)): if not dates is False: d0,d1=dates if t[it]<d0 or t[it]>=d1: continue n+=1 u=netcdf.use(nc0,uvar,**{xdim:XI,ydim:ETA,tdim:it}) v=netcdf.use(nc0,vvar,**{xdim:XI,ydim:ETA,tdim:it}) # rotate uv: if angvar: print 'rotating ...' u,v=calc.rot2d(u,v,-ang) nc.vars['time'][n]=time[it] print 'filling uv',n,t[it] nc.vars['air_u'][n,...]=u nc.vars['air_v'][n,...]=v nc.close() nc0.close() ncg.close()
def tick_values(self, vmin, vmax): vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander=1e-7, tiny=1e-13) lower = netcdftime.num2date(vmin, self.date_unit, self.calendar) upper = netcdftime.num2date(vmax, self.date_unit, self.calendar) self.ndays = abs(vmax - vmin) resolution, n = self.compute_resolution(vmin, vmax, lower, upper) if resolution == 'YEARLY': # TODO START AT THE BEGINNING OF A DECADE/CENTURY/MILLENIUM as appropriate. years = self._max_n_locator.tick_values(lower.year, upper.year) ticks = [netcdftime.datetime(int(year), 1, 1) for year in years] elif resolution == 'MONTHLY': # TODO START AT THE BEGINNING OF A DECADE/CENTURY/MILLENIUM as appropriate. months_offset = self._max_n_locator.tick_values(0, n) ticks = [] for offset in months_offset: year = lower.year + np.floor((lower.month + offset) / 12) month = ((lower.month + offset) % 12) + 1 ticks.append(netcdftime.datetime(int(year), int(month), 1)) elif resolution == 'DAILY': # TODO: It would be great if this favoured multiples of 7. days = self._max_n_locator_days.tick_values(vmin, vmax) ticks = [ netcdftime.num2date(dt, self.date_unit, self.calendar) for dt in days ] elif resolution == 'HOURLY': hour_unit = 'hours since 2000-01-01' in_hours = netcdftime.date2num([lower, upper], hour_unit, self.calendar) hours = self._max_n_locator.tick_values(in_hours[0], in_hours[1]) ticks = [ netcdftime.num2date(dt, hour_unit, self.calendar) for dt in hours ] elif resolution == 'MINUTELY': minute_unit = 'minutes since 2000-01-01' in_minutes = netcdftime.date2num([lower, upper], minute_unit, self.calendar) minutes = self._max_n_locator.tick_values(in_minutes[0], in_minutes[1]) ticks = [ netcdftime.num2date(dt, minute_unit, self.calendar) for dt in minutes ] elif resolution == 'SECONDLY': second_unit = 'seconds since 2000-01-01' in_seconds = netcdftime.date2num([lower, upper], second_unit, self.calendar) seconds = self._max_n_locator.tick_values(in_seconds[0], in_seconds[1]) ticks = [ netcdftime.num2date(dt, second_unit, self.calendar) for dt in seconds ] else: raise ValueError( 'Resolution {} not implemented yet.'.format(resolution)) return netcdftime.date2num(ticks, self.date_unit, self.calendar)
def his2gnome(fname,his,grd=False,nomask=False,gshhsMask=True,xylim=False,dates=False,ij=(1,1)): ''' Creates GNOME wind file Ex: his2gnome(out,his,grd,dates=dates,ij=(2,2)) if gshhsMask, the high res mask file mask_gshhs.npy will be created at 1st usage. Mask is based on high (h) resolution gshhs data which must be available (env variable GSHHS_MASK must be set). ''' if not grd: grd=his deta,dxi=ij dims=netcdf.fdim(his) xi,eta=dims['xi_rho'],dims['eta_rho'] xi0,eta0=xi,eta nc0=netcdf.ncopen(his) time=netcdf.nctime(nc0,'ocean_time') # for roms agrif: #t=netcdf.use(nc0,'scrum_time') #time=netcdftime.num2date(t,'seconds since %d-01-01' % year0) x0=netcdf.use(grd,'lon_rho') y0=netcdf.use(grd,'lat_rho') ang=netcdf.use(grd,'angle') if not xylim is False: xlim=xylim[:2] ylim=xylim[2:] i1,i2,j1,j2=calc.ij_limits(x0,y0,xlim,ylim) print i1,i2,j1,j2 xi=i2-i1 eta=j2-j1 else: i1,i2=0,xi j1,j2=0,eta XI ='%d:%d:%d' %(i1,i2,dxi) ETA ='%d:%d:%d' %(j1,j2,deta) xi=len(range(i1,i2,dxi)) eta=len(range(j1,j2,deta)) # create file: create_uv(fname,xi,eta) nc=netcdf.ncopen(fname,'a') for v0,v in ('lon_rho','lon'),('lat_rho','lat'),('mask_rho','mask'),('h','depth'): print 'filling %s with %s' % (v,v0) nc.vars[v][:]=netcdf.use(grd,v0,xi_rho=XI,eta_rho=ETA) if nomask: print 'NO MASK !!!' nc.vars['mask'][:]=1 if gshhsMask: try: mask=np.load('mask_gshhs.npy') except: mask=1+0*netcdf.use(nc0,'mask_rho',xi_rho=XI,eta_rho=ETA) mask=mask.astype('bool') x=netcdf.use(grd,'lon_rho',xi_rho=XI,eta_rho=ETA) y=netcdf.use(grd,'lat_rho',xi_rho=XI,eta_rho=ETA) from okean import gshhs axis=x.min(),x.max(),y.min(),y.max() g=gshhs.gshhs(axis, resolution='h',area_thresh=0., max_level=2,clip=True) for lon, lat, level in zip(g.lon, g.lat, g.level): if level == 1: # land print 'mask ',lon.shape i=calc.inpolygon(x,y,lon,lat) mask=mask & ~i mask.dump('mask_gshhs.npy') nc.vars['mask'][:]=mask x=x0[j1:j2:deta,i1:i2:dxi] y=y0[j1:j2:deta,i1:i2:dxi] ang=ang[j1:j2:deta,i1:i2:dxi] n=-1 for it in range(len(time)): if not dates is False: d0,d1=dates if time[it]<d0 or time[it]>=d1: continue n+=1 U=np.zeros((eta0,xi0),'f') V=np.zeros((eta0,xi0),'f') nc.vars['time'][n]=netcdftime.date2num(time[it],tunits) # for roms agrif: #u=netcdf.use(nc0,'u',time=it,s_rho=-1) #v=netcdf.use(nc0,'v',time=it,s_rho=-1) u=netcdf.use(nc0,'u',ocean_time=it,s_rho=-1) v=netcdf.use(nc0,'v',ocean_time=it,s_rho=-1) # mask extrap: print 'mask extrap...' u=calc.mask_extrap(x0,y0,np.ma.masked_where(u==0,u)) v=calc.mask_extrap(x0,y0,np.ma.masked_where(v==0,v)) U[:,1:-1]=0.5*(u[:,:-1]+u[:,1:]) U[:,0]=u[:,0] U[:,-1]=u[:,-1] V[1:-1,:]=0.5*(v[:-1.:]+v[1:,:]) V[0,:]=v[0,:] V[-1,:]=v[-1,:] U=U[j1:j2,i1:i2] V=V[j1:j2,i1:i2] U=U[j1:j2:deta,i1:i2:dxi] V=V[j1:j2:deta,i1:i2:dxi] # rotate uv: print 'rotating ...' U,V=calc.rot2d(U,V,-ang) print 'filling uv', n, time[it] nc.vars['u'][n,...]=U nc.vars['v'][n,...]=V nc.close() nc0.close()