bronx.stdtypes.date¶
Classes and functions form this module are dedicated to the manipulation of date and time quantities.
Obviously the main classes of this module are Date, Period,
Time and Month.
Some helper functions are also provided (to get the current date, …).
Formats hypothesis:
Ideally dates and times should be represented as a valid ISO 8601 strings. Here are a few exemples:
2016-01-01 or 20160101 (for a date)
12:00, 1200, 12:00:00 or 120000 (for a time)
A combination of both: 2016-01-01T12:00
Optionally the time zone indicator: 2016-01-01T12:00Z
For a date, the following will also be accepted yyyymmdd[hh[mn[ss]]] with yyyy as the year in 4 numbers, mm as the month in 2 numbers, dd as the day in 2 numbers, hh as the hours (0-24), mn as the minutes and ss as the seconds.
For time periods, the following convention applies:
P starts an ISO 8601 Period definition
nY, the number of years (n positive integer),
nM, the number of months (n positive integer),
nD, the number of days (n positive integer),
T as a time separator,
nH, the number of hours (n positive integer),
nM, the number of minutes (n positive integer),
nS, the number of seconds (n positive integer)
- Examples:
P1Y <=> is a 1 year period
P20D <=> is a 20 days period
PT15H10M55S <=> is a 15 hours, 10 minutes and 55 seconds period
Module Attributes¶
- bronx.stdtypes.date.local_date_functions = {'at_hour': <function at_hour>, 'at_minute': <function at_minute>, 'at_second': <function at_second>, 'easter': <function easter>, 'lastround': <function lastround>, 'now': <function now>, 'synop': <function synop>, 'today': <function today>, 'tomorrow': <function tomorrow>, 'utcnow': <function utcnow>, 'yesterday': <function yesterday>}
The list of helper date functions
Functions¶
- bronx.stdtypes.date.at_second()[source]¶
Return the date just now, with only hours, minutes and seconds.
- bronx.stdtypes.date.daterange(start, end=None, step='P1D')[source]¶
Date generator.
- Parameters:
daterange()always returns a generator object:>>> daterange('2017010100', '2017013100', 'P14D') <generator object daterange at 0x...> >>> list(daterange('2017010100', '2017013100', 'P14D')) [Date(2017, 1, 1, 0, 0), Date(2017, 1, 15, 0, 0), Date(2017, 1, 29, 0, 0)]
The start and end attributes are always sorted:
>>> list(daterange('2017013100', '2017010100', 'P14D')) [Date(2017, 1, 1, 0, 0), Date(2017, 1, 15, 0, 0), Date(2017, 1, 29, 0, 0)]
When end is not provided, it is assumed to be 10 days after start:
>>> list(daterange('2017010100')) [Date(2017, 1, 1, 0, 0), Date(2017, 1, 2, 0, 0), Date(2017, 1, 3, 0, 0), Date(2017, 1, 4, 0, 0), Date(2017, 1, 5, 0, 0), Date(2017, 1, 6, 0, 0), Date(2017, 1, 7, 0, 0), Date(2017, 1, 8, 0, 0), Date(2017, 1, 9, 0, 0), Date(2017, 1, 10, 0, 0), Date(2017, 1, 11, 0, 0)]
- bronx.stdtypes.date.daterangex(start, end=None, step=None, shift=None, fmt=None, prefix=None)[source]¶
Extended date range expansion (returns a list).
Except when
fmtorprefixare specified, a list ofDateobjects is returned.daterangex()accepts many arguments combinations:>>> daterangex('2017010100', '2017013100', 'P14D') [Date(2017, 1, 1, 0, 0), Date(2017, 1, 15, 0, 0), Date(2017, 1, 29, 0, 0)] >>> daterangex('2017010100-2017013100-P14D') [Date(2017, 1, 1, 0, 0), Date(2017, 1, 15, 0, 0), Date(2017, 1, 29, 0, 0)] >>> daterangex('2017010100/2017013100/P14D') [Date(2017, 1, 1, 0, 0), Date(2017, 1, 15, 0, 0), Date(2017, 1, 29, 0, 0)]
lists, tuples or comma-separated string can be provided:
>>> daterangex(['2017010100-2017013100-P14D', ... '2017060100-2017063000-P14D', ... '2017122500']) [Date(2017, 1, 1, 0, 0), Date(2017, 1, 15, 0, 0), Date(2017, 1, 29, 0, 0), Date(2017, 6, 1, 0, 0), Date(2017, 6, 15, 0, 0), Date(2017, 6, 29, 0, 0), Date(2017, 12, 25, 0, 0)] >>> daterangex('2017010100-2017013100-P14D,' + ... '2017060100-2017063000-P14D,' + ... '2017122500') [Date(2017, 1, 1, 0, 0), Date(2017, 1, 15, 0, 0), Date(2017, 1, 29, 0, 0), Date(2017, 6, 1, 0, 0), Date(2017, 6, 15, 0, 0), Date(2017, 6, 29, 0, 0), Date(2017, 12, 25, 0, 0)]
Extra features are provided such as ; applying a global shift:
>>> daterangex('2017010100-2017013100-P14D,2017060100-2017063000-P14D,2017122500', ... shift='P1D') [Date(2017, 1, 2, 0, 0), Date(2017, 1, 16, 0, 0), Date(2017, 1, 30, 0, 0), Date(2017, 6, 2, 0, 0), Date(2017, 6, 16, 0, 0), Date(2017, 6, 30, 0, 0), Date(2017, 12, 26, 0, 0)]
Formatting the date as a string depending on the fmt function name:
>>> daterangex('2017010100-2017013100-P14D,2017060100-2017063000-P14D,2017122500', ... fmt='ymdh') [...'2017010100', ...'2017011500', ...'2017012900', ...'2017060100', ...'2017061500', ...'2017062900', ...'2017122500']
Formatting the date as a string depending on the fmt format string:
>>> daterangex('2017010100-2017013100-P14D,2017060100-2017063000-P14D,2017122500', ... fmt='{0.year:04d}') [...'2017']
Adding a prefix before the date string:
>>> daterangex('2017010100-2017013100-P14D,2017060100-2017063000-P14D,2017122500', ... fmt='ymdh', prefix='loop') [...'loop2017010100', ...'loop2017011500', ...'loop2017012900', ...'loop2017060100', ...'loop2017061500', ...'loop2017062900', ...'loop2017122500']
- bronx.stdtypes.date.easter(year=None)[source]¶
Return the date for easter of the given year
>>> dates = [2013, 2014, 2015, 2016, 2017, 2018] >>> [easter(d).ymd for d in dates] [...'20130331', ...'20140420', ...'20150405', ...'20160327', ...'20170416', ...'20180401']
- bronx.stdtypes.date.guess(*args)[source]¶
Do our best to find a
DateorPeriodobject compatible withargs.
- bronx.stdtypes.date.lastround(rh=1, delta=0, base=None)[source]¶
Return the date just before
basewith a plain hour multiple ofrh.
- bronx.stdtypes.date.now()[source]¶
Return the date just now, with hours, minutes, seconds and microseconds.
- bronx.stdtypes.date.synop(delta=0, base=None, time=None, step=6)[source]¶
Return the date associated to the last synoptic hour.
- bronx.stdtypes.date.timeintrangex(start, end=None, step=None, shift=None, fmt=None, prefix=None)[source]¶
Extended range expansion (returns a list).
This function is built on top of
timerangex(). It uses theTimeIntclass instead of theTimeclass. Practically, if the ‘range’ is just made of basic integers (e.g. just hours), a list of integers is returned. If minutes are needed, a list of string formated as ‘hhhh:mm’ is returned.When
startis already a complex definition (as a string),endandsteponly apply as default when the sub-definition instartdoes not contain anyendorstepvalue.All the examples below refers to
timeintrangex(). However, they are fully relevant forrangex()(since it is an alias oftimeintrangex()).Basic examples:
>>> timeintrangex(0, 12, 3) [0, 3, 6, 9, 12] >>> timeintrangex('0-12-3') [0, 3, 6, 9, 12] >>> timeintrangex('0-12-3', shift=24) [24, 27, 30, 33, 36] >>> timeintrangex(0, 12, 3, shift=24) [24, 27, 30, 33, 36] >>> print(', '.join(timeintrangex('0-12-3', shift=24, fmt='%03d'))) 024, 027, 030, 033, 036
Hour/Minutes examples:
>>> print(', '.join(timeintrangex(0, 3, '0:30'))) 0000:00, 0000:30, 0001:00, 0001:30, 0002:00, 0002:30, 0003:00 >>> print(', '.join(timeintrangex('0:00', '3:00', '0:30'))) 0000:00, 0000:30, 0001:00, 0001:30, 0002:00, 0002:30, 0003:00 >>> print(', '.join(timeintrangex(0, 3, '0:30', shift=24))) 0024:00, 0024:30, 0025:00, 0025:30, 0026:00, 0026:30, 0027:00
It also works with negative values:
>>> print(', '.join(timeintrangex(3, 0,'-0:30'))) 0000:00, 0000:30, 0001:00, 0001:30, 0002:00, 0002:30, 0003:00 >>> print(', '.join(timeintrangex(-3, 0,'0:30'))) -0000:30, -0001:00, -0001:30, -0002:00, -0002:30, -0003:00, 0000:00 >>> timeintrangex(-3, 0, 1) [-3, -2, -1, 0]
With complex strings:
>>> timeintrangex('0-12-3,18-36-6,48') [0, 3, 6, 9, 12, 18, 24, 30, 36, 48]
- bronx.stdtypes.date.timerangex(start, end=None, step=None, shift=None, fmt=None, prefix=None)[source]¶
Extended time range expansion (returns a list).
Except when
fmtorprefixare specified, a list ofTimeobjects is returned.When
startis already a complex definition (as a string),endandsteponly apply as default when the sub-definition instartdoes not contain anyendorstepvalue.Basic examples:
>>> timerangex(0, 12, 3) [Time(0, 0), Time(3, 0), Time(6, 0), Time(9, 0), Time(12, 0)] >>> timerangex('0-12-3') [Time(0, 0), Time(3, 0), Time(6, 0), Time(9, 0), Time(12, 0)] >>> timerangex('0-12-3', shift=24) [Time(24, 0), Time(27, 0), Time(30, 0), Time(33, 0), Time(36, 0)] >>> timerangex(0, 12, 3, shift=24) [Time(24, 0), Time(27, 0), Time(30, 0), Time(33, 0), Time(36, 0)] >>> print(', '.join(timerangex('0-12-3', shift=24, fmt='{0.hour:03d}'))) 024, 027, 030, 033, 036 >>> print(', '.join(timerangex('0-12-3', shift=24, fmt='fmthm'))) 0024:00, 0027:00, 0030:00, 0033:00, 0036:00
Hour/Minutes examples:
>>> timerangex(0, 3, '0:30') [Time(0, 0), Time(0, 30), Time(1, 0), Time(1, 30), Time(2, 0), Time(2, 30), Time(3, 0)] >>> timerangex('0:00', '3:00', '0:30') [Time(0, 0), Time(0, 30), Time(1, 0), Time(1, 30), Time(2, 0), Time(2, 30), Time(3, 0)] >>> timerangex(0, 3, '0:30', shift=24) [Time(24, 0), Time(24, 30), Time(25, 0), Time(25, 30), Time(26, 0), Time(26, 30), Time(27, 0)]
It also works with negative values:
>>> timerangex(3, 0,'-0:30') [Time(0, 0), Time(0, 30), Time(1, 0), Time(1, 30), Time(2, 0), Time(2, 30), Time(3, 0)] >>> timerangex(-3, 0,'0:30') [Time(-3, 0), Time(-2, -30), Time(-2, 0), Time(-1, -30), Time(-1, 0), Time(0, -30), Time(0, 0)] >>> timerangex(-3, 0, 1) [Time(-3, 0), Time(-2, 0), Time(-1, 0), Time(0, 0)]
With complex strings:
>>> timerangex('0-12-3,18-36-6,48') [Time(0, 0), Time(3, 0), Time(6, 0), Time(9, 0), Time(12, 0), Time(18, 0), Time(24, 0), Time(30, 0), Time(36, 0), Time(48, 0)]
- bronx.stdtypes.date.tomorrow(base=None)[source]¶
Return the date of tomorrow (relative to today or specified
basedate).
Classes¶
- class bronx.stdtypes.date.Date(*args, **kw)[source]¶
Bases:
datetime,_GetattrCalculatorMixinStandard date objects, extending
datetime.datetimefeatures with iso8601 capabilities.- The object can be constructed from:
a standard
datetime.datetimeobject;named attributes compatible with the
datetime.datetimeclass;a Vortex’s
Dateobject;a tuple containing at least (year, month, day) values (optionally hours);
a string that could be reshaped as an ISO 8601 date string.
a string with one or more time deltas (e.g. 201509010600/-PT1H/-PT2H)
the name of one of the helper date functions (see below)
a float representing a number of seconds since the epoch time
Here are a few equivalent examples:
Date(2017, 1, 1, 12, 0) >>> Date(2017, 1, 1, 12) Date(2017, 1, 1, 12, 0) >>> Date([2017, 1, 1, 12]) Date(2017, 1, 1, 12, 0) >>> Date('2017-01-01T12:00') Date(2017, 1, 1, 12, 0) >>> Date('2017010112') Date(2017, 1, 1, 12, 0)
Helper functions can be used:
>>> Date('now') Date(2017, 8, 21, 19, 33, 46) >>> Date('easter') Date(2017, 4, 16, 0, 0)
Let’s do some calculations while creating the object:
>>> Date('20170101/PT12H') Date(2017, 1, 1, 12, 0) >>> Date('2017010212/-P1D') Date(2017, 1, 1, 12, 0) >>> Date('2017010200/-P1D/PT12H') Date(2017, 1, 1, 12, 0)
The addition is defined (if the operand is not a
Periodobject, a conversion is attempted):>>> Date('2017010100') + Period('PT12H') Date(2017, 1, 1, 12, 0) >>> Date('2017010100') + Time(12, 00) Date(2017, 1, 1, 12, 0) >>> Date('2017010100') + 'PT12H' Date(2017, 1, 1, 12, 0) >>> Date('2017010100') + 43200 Date(2017, 1, 1, 12, 0)
The subtraction is also defined (the operand can be either a
Periodobject or aDateobject):>>> Date('2017010100') - Period('PT12H') Date(2016, 12, 31, 12, 0) >>> Date('2017010100') - 'PT12H' Date(2016, 12, 31, 12, 0) >>> Date('2017010100') - Date('2017010212') Period(days=-2, seconds=43200) >>> Date('2017010100') - '2017010212' Period(days=-2, seconds=43200)
Comparison operators are all available.
The
Datealso have the ability to generate dynamic properties on the fly (because it inherits the_GetattrCalculatorMixinmix in). Such dynamic properties can be very useful when used withfootprintspackage substitution mechanism. It allows to do calculations on the fly:>>> date = Date('20170416') >>> date Date(2017, 4, 16, 0, 0) >>> date.addPT6H Date(2017, 4, 16, 6, 0) >>> date.subP1D Date(2017, 4, 15, 0, 0) >>> date.subP1D_addPT6H Date(2017, 4, 15, 6, 0) >>> print(date.subP1D_ymdh) 2017041500
The following will also work:
>>> print(date.addterm_ymdh(dict(term=Time(6, 0)), dict())) 2017041606
In such a documentation, this looks horrible. However, in the context of
footprintssubstitutions, it works like a charm (to compute the validity date of a a resource that defines a term).- as_datetime()[source]¶
Silly enough, but could be usefull to retrieve a raw
datetime.datetimeobject.
- property dd¶
DD formated string.
- property epoch¶
Seconds since the beginning of epoch… the first of january, 1970.
- from_cnesjulian(jdays=None)[source]¶
>>> d = Date('20111025') >>> d.from_cnesjulian() Date(2011, 10, 25, 0, 0) >>> d.from_cnesjulian(22578) Date(2011, 10, 26, 0, 0)
- property h¶
H formated string.
- property hh¶
HH formated string.
- property hm¶
HHMM formated string.
- property julian¶
Returns Julian day.
- property midcross¶
Return the closest day out of this month.
- property mm¶
MM (month) formated string.
- monthrange(year=None, month=None)[source]¶
Return the number of days in the current of specified year-month couple.
- property nivologyseason¶
Return the nivology season of a current date
- property nivologyseason_begin¶
Return the begin date of the current nivology season.
- property origin¶
Origin date… far far ago at the very beginning of the 70’s.
- property outbound¶
Return the closest day out of this month.
- property stdvortex¶
Semi-compact representation for vortex paths (without cutoff).
- to_cnesjulian(date=None)[source]¶
Convert current Date() object, or arbitrary date, to CNES julian calendar
>>> d = Date('20111026') >>> d.to_cnesjulian() 22578 >>> d.to_cnesjulian(date=[2011, 10, 27]) 22579
- property y¶
YYYYMMDDHH formated string.
- property ymd¶
YYYYMMDD formated string.
- property ymd6h¶
YYMMDDHH formated string with HH=6:00.
- property ymdHh¶
SURFEX-SODA hour format yymmddHhh ex : 140331H10
- property ymdh¶
YYYYMMDDHH formated string.
- property ymdhm¶
YYYYMMDDHHMM formated string.
- property ymdhms¶
YYYYMMDDHHMMSS formated string.
- property yymd¶
YYMMDD formated string.
- property yymdh¶
YYMMDDHH formated string.
- class bronx.stdtypes.date.Month(*args, **kw)[source]¶
Bases:
objectBasic class for handling a month number, according to an explicit or implicit year.
- The object can be constructed from:
a standard
datetime.datetimeobject or aDateobject;a
Monthobject;named attributes compatible with the
datetime.datetimeclass;a unique integer representing the Month number (in such a case, the year is assumed to be the current year);
a tuple containing two integer representing (month, year) values;
any string supported by the
Dateobject;
Here are a few equivalent examples:
>>> Month(year=2016, month=1, day=1) Month(01, year=2016) >>> Month('2016010100') Month(01, year=2016) >>> Month(1, 2016) Month(01, year=2016)
The year may not be specified (in such a case the current year is used):
>>> Month(1) Month(01, year=2017)
When initialising the object with a string, some nice helpers are provided:
>>> Month('2016010100:prev') Month(12, year=2015) >>> Month('2016010100:next') Month(02, year=2016) >>> Month('2016011500:closest') Month(12, year=2015) >>> Month('2016011600:closest') Month(02, year=2016)
Concerted to an integer, this object returns the month number:
>>> int(Month('2016010100')) 1
The addition and subtraction is defined (the operand can be an integer, a
Periodobject, or a string that can be converted to aPeriodobject):>>> Month('2016010100') + 1 Month(02, year=2016) >>> Month('2016010100') + Period('P2M') Month(03, year=2016) >>> Month('2016010100') + 'P2M' Month(03, year=2016) >>> Month('2016010100') - 'P2M' Month(10, year=2015)
Some kind of comparisons are possible:
>>> Month('2016010100') == 1 True >>> Month('2016010100') < 2 True >>> Month('2016010100') > 1 False >>> Month('2016010100') > Month('2015100100') True
- property fmtraw¶
YYYYMM formated string.
- property fmtym¶
YYYY-MM formated string.
- property month¶
The month number.
- property year¶
The year number.
- class bronx.stdtypes.date.Period(*args, **kw)[source]¶
Bases:
timedeltaStandard period objects, extending
datetime.timedeltafeatures with iso8601 capabilities.- The object can be constructed from:
a standard
datetime.timedeltaobject;named attributes compatible with the
datetime.timedeltaclass;a string that could be reshaped as an ISO 8601 date string (see the description of the ISO 8601 convention at the top of this page);
one integer or float (number of seconds)
two integers (number of days, number of seconds)
These four objects are identical:
>>> Period(days=2, hours=1, seconds=30) Period(days=2, seconds=3630) >>> Period('P2DT1H30S') Period(days=2, seconds=3630) >>> Period(176430) Period(days=2, seconds=3630) >>> Period(2, 3630) Period(days=2, seconds=3630)
Addition and subtraction are implemented (if the other operand is not a
Periodobject, a conversion is attempted):>>> Period('PT6H') + Period('PT6H') Period(seconds=43200) >>> Period('PT6H') + 'PT6H' Period(seconds=43200) >>> Period('PT6H') + 43200 Period(seconds=64800)
Multiplication (by an integer) is implemented:
>>> Period('PT6H') * 2 Period(seconds=43200)
Comparison operators are all available.
- property hms¶
Nicely formatted HH:MM:SS string.
- property hmscompact¶
Compact HHMMSS string.
- property length¶
Absolute length in seconds.
- property pminutes¶
The period expressed in minnutes (float)
- property pseconds¶
The period expressed in seconds (integer)
- class bronx.stdtypes.date.Time(*args, **kw)[source]¶
Bases:
_GetattrCalculatorMixinBasic object to handle hh:mm information.
Extended arithmetic is supported.
- The object can be constructed from:
a standard
datetime.timeobject;a
Timeobjecta
Periodobjectnamed attributes compatible with the
datetime.timeclass;a string that could be reshaped as a
Periodobject.a string that could be reshaped as an ISO 8601 time string.
two integers (hours, minutes)
a tuple containing (hour, minute) values;
Here are a few equivalent examples:
>>> Time('18:05') Time(18, 5) >>> Time('18h05') Time(18, 5) >>> Time('18-05') Time(18, 5) >>> Time('T18:05Z') Time(18, 5) >>> Time(18, 5) Time(18, 5) >>> Time((18, 5)) Time(18, 5) >>> Time('PT18H05M') Time(18, 5) >>> Time(hour=18, minute=5) Time(18, 5)
When constructed from strings, the
Timeobject can handle negative values:>>> Time('-18:05') Time(-18, -5) >>> Time('-PT18H05M') Time(-18, -5)
The addition and subtraction is defined (if the operand is not a
Timeobject, a conversion is attempted):>>> Time('12:00') + Time('06:30') Time(18, 30) >>> Time('12:00') + '06:30' Time(18, 30) >>> Time('12:00') + 'PT06H30M' Time(18, 30) >>> Time('12:00') - 'PT06H30M' Time(5, 30)
Let’s do some calculations while creating the object:
>>> Time('12:00/PT6H') Time(18, 0) >>> Time('-PT12H/-P1D/PT12H') Time(-24, 0)
Comparison operators are all available.
The
Timealso have the ability to generate dynamic properties on the fly (because it inherits the_GetattrCalculatorMixinmix in). Such dynamic properties can be very useful when used withfootprintspackage substitution mechanism.It allows to do calculations on the fly:
>>> atime = Time('12:00') >>> atime.add06h30 Time(18, 30) >>> atime.addPT6H30M Time(18, 30) >>> print(atime.addPT6H30M_fmthm) 0018:30 >>> print(atime.subPT18H30M_fmthm) -0006:30
- property dhm¶
Return a tuple with the number of (days, hours, minutes).
- property fmtdhm¶
DDHHMM formated string.
- property fmth¶
HHHH formated string.
- property fmthhmm¶
HH:MM formated string.
- property fmthm¶
HHHH:MM formated string.
- property fmthour¶
HHHH formated string.
- property fmtraw¶
HHHHMM formated string.
- property fmtraw2¶
HHHHHHHHMM formated string.
- property hour¶
The number of hours
- property minute¶
The number of minutes