Skip to content

Datetime dev #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
Jun 16, 2011
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e64b6f1
ENH: datetime-autounit: Automatically detect the unit for scalar cons…
Jun 7, 2011
6395979
ENH: datetime-autounit: Make 'now' and 'today' only parse with approp…
Jun 7, 2011
ab2ac7c
ENH: datetime-promotion: Unify datetime/timedelta type promotion
Jun 7, 2011
fdb4190
BUG: datetime: Had int instead of Py_ssize_t for an AsStringAndSize call
Jun 8, 2011
487874a
ENH: datetime-arange: Add boilerplate for the specialized datetime_ar…
Jun 8, 2011
50261be
ENH: datetime-arange: Filling in the datetime-specific arange function
Jun 8, 2011
d6c63e3
ENH: datetime-meta: Add generic units as a datetime unit type
Jun 8, 2011
5c16411
ENH: datetime-arange: Use the generic units for parameter conversion
Jun 9, 2011
53ab0c1
ENH: datetime-arange: The arange function largely works now
Jun 9, 2011
98b4c38
ENH: datetime-arange: Detect the unit when a dtype with generic units…
Jun 9, 2011
dadf6c2
ENH: datetime-arange: Move the unit metadata promotion to a separate …
Jun 9, 2011
c3f963e
ENH: datetime-bday: Remove business days as a datetime metadata unit
Jun 9, 2011
e24e9d4
ENH: datetime-bday: Add datetime_busday.c/.h, start busday_offset fun…
Jun 10, 2011
4fced4a
ENH: datetime-bday: Implement the weekmask part of the busday_offset …
Jun 10, 2011
8a8a84a
ENH: datetime-bday: Connect busday_offset so it can be called from Py…
Jun 10, 2011
db62c35
ENH: datetime-autounit: Unit detection working with arrays, fix ufunc…
Jun 10, 2011
29a3ceb
TST: datetime-bday: Write some tests for busday_offset
Jun 10, 2011
3d8fda5
ENH: datetime-bday: Functions to get and normalize a list of holidays
Jun 13, 2011
b90d182
ENH: datetime-bday: Get holidays working with busday_offset
Jun 13, 2011
68f1cf2
ENH: datetime-bday: Create the np.busdaydef business day definition o…
Jun 13, 2011
e164d94
ENH: datetime-bday: Cache the business day count in the weekmask in b…
Jun 14, 2011
f7ae666
ENH: datetime-bday: Move the weekmask and holidays list convertors to…
Jun 14, 2011
0418574
ENH: datetime-bday: Got busday_count function working
Jun 14, 2011
84e1f7d
ENH: datetime-bday: Got is_busday function working, completed busines…
Jun 14, 2011
6b5a42a
DOC: datetime-bday: Document the datetime business day functions
Jun 14, 2011
6376ba8
DOC: datetime-feedback: Various comment/documentation tweaks from Chu…
Jun 15, 2011
d117335
STY: datetime-feedback: Rename np.busdaydef -> np.busdaycalendar
Jun 15, 2011
31056d4
DOC: datetime-feedback: Applying Ralf's feedback for the parameter co…
Jun 15, 2011
abfec95
STY: datetime-feedback: Expand some comments and adjust spacing based…
Jun 16, 2011
e6bffff
BUG: dtype: Cleanups and fix parsing datetime dtypes with an endian s…
Jun 16, 2011
8019d91
BUG: core: promote_types wasn't always returning NBO data types
Jun 16, 2011
afe25c1
BUG: ufunc: Type promotion output must always be in NBO (fixes #1867)
Jun 16, 2011
e9f4e75
BUG: Py3k: some of the string type-related failures in numpy/core/tests
Jun 13, 2011
2d7d59a
ENH: datetime-ufunc: Add m8 / m8 -> f8 case to the datetime ufunc ope…
Jun 16, 2011
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions doc/source/reference/routines.datetime.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.. _routines.datetime:

Datetime Support Functions
**************************

.. currentmodule:: numpy

Business Day Functions
======================

.. currentmodule:: numpy

.. autosummary::
:toctree: generated/

busdaycalendar
is_busday
busday_offset
busday_count

1 change: 1 addition & 0 deletions doc/source/reference/routines.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ indentation.
routines.math
routines.functional
routines.poly
routines.datetime
routines.financial
routines.set
routines.window
Expand Down
266 changes: 266 additions & 0 deletions numpy/add_newdocs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5934,6 +5934,272 @@ def luf(lamdaexpr, *args, **kwargs):
"""))


##############################################################################
#
# Datetime-related Methods
#
##############################################################################

add_newdoc('numpy.core.multiarray', 'busdaycalendar',
"""
busdaycalendar(weekmask='1111100', holidays=None)

A business day calendar object that efficiently stores
information defining business days for the business
day-related functions.

Parameters
----------
weekmask : str or array_like of bool, optional
A seven-element array indicating which of Monday through Sunday may
be valid business days. May be specified as a list or array, like
[1,1,1,1,1,0,0], a length-seven string like '1111100', or a string
of three-letter weekday names, like 'MonTueWedThuFri'. The latter
string representation is most useful when only one day of the
week is important, like 'Mon' if you want to calculate the date
of Easter.
holidays : array_like of datetime64[D], optional
An array of dates which should be blacked out from being considered
as business days. They may be specified in any order, and NaT
(not-a-time) dates are ignored. Internally, this list is normalized
into a form suited for fast business day calculations.

Returns
-------
out : busdaycalendar
A business day calendar object containing the specified
weekmask and holidays.

See Also
--------
is_busday : Returns a boolean array indicating valid business days.
busday_offset : Applies an offset counted in business days.
busday_count : Counts how many business days are in a half-open date range.

Attributes
----------
weekmask : seven-element array of bool
holidays : sorted array of datetime64[D]

Examples
--------
>>> # Some important days in July
... bdd = np.busdaycalendar(
... holidays=['2011-07-01', '2011-07-04', '2011-07-17'])
>>> # Default is Monday to Friday weekdays
... bdd.weekmask
array([ True, True, True, True, True, False, False], dtype='bool')
>>> # Any holidays already on the weekend are removed
... bdd.holidays
array(['2011-07-01', '2011-07-04'], dtype='datetime64[D]')
""")

add_newdoc('numpy.core.multiarray', 'busdaycalendar', ('weekmask',
"""A copy of the seven-element boolean mask indicating valid business days."""))

add_newdoc('numpy.core.multiarray', 'busdaycalendar', ('holidays',
"""A copy of the holiday array indicating blacked out business days."""))

add_newdoc('numpy.core.multiarray', 'is_busday',
"""
is_busday(dates, weekmask='1111100', holidays=None, busdaycal=None, out=None)

Calculates which of the given dates are valid business days, and
which are not.

Parameters
----------
dates : array_like of datetime64[D]
The array of dates to process.
weekmask : str or array_like of bool, optional
A seven-element array indicating which of Monday through Sunday may
be valid business days. May be specified as a list or array, like
[1,1,1,1,1,0,0], a length-seven string like '1111100', or a string
of three-letter weekday names, like 'MonTueWedThuFri'. The latter
string representation is most useful when only one day of the
week is important, like 'Mon' if you want to calculate the date
of Easter.
holidays : array_like of datetime64[D], optional
An array of dates which should be blacked out from being considered
as business days. They may be specified in any order, and NaT
(not-a-time) dates are ignored. Internally, this list is normalized
into a form suited for fast business day calculations.
busdaycal : busdaycalendar, optional
A `busdaycalendar` object which specifies the business days. If this
parameter is provided, neither weekmask nor holidays may be
provided.
out : array of bool, optional
If provided, this array is filled with the result.

Returns
-------
out : array of bool
An array with the same shape as ``dates``, containing True for
each valid business day, and False for the others.

See Also
--------
busdaycalendar: An object for efficiently specifying which are business days.
busday_offset : Applies an offset counted in business days.
busday_count : Counts how many business days are in a half-open date range.

Examples
--------
>>> # The weekdays are Friday, Saturday, and Monday
... np.is_busday(['2011-07-01', '2011-07-02', '2011-07-18'],
... holidays=['2011-07-01', '2011-07-04', '2011-07-17'])
array([False, False, True], dtype='bool')
""")

add_newdoc('numpy.core.multiarray', 'busday_offset',
"""
busday_offset(dates, offsets, roll='raise', weekmask='1111100', holidays=None, busdaycal=None, out=None)

First adjusts the date to fall on a business day according to
the ``roll`` rule, then applies offsets to the given dates
counted in business days.

Parameters
----------
dates : array_like of datetime64[D]
The array of dates to process.
offsets : array_like of int
The array of offsets, which is broadcast with ``dates``.
roll : {'raise', 'nat', 'forward', 'following', 'backward', 'preceding', 'modifiedfollowing', 'modifiedpreceding'}, optional
How to treat dates that do not fall on a business day. The default
is 'raise'.

* 'raise' means to raise an exception for invalid business days.
* 'nat' means to return a NaT (not-a-time) for invalid business days.
* 'forward' and 'following' mean to take the first business day
later in time.
* 'backward' and 'preceding' mean to take the first business day
earlier in time.
* 'modifiedfollowing' means to take the first business day
later in time unless it is across a Month boundary, in which
case to take the first business day earlier in time.
* 'modifiedpreceding' means to take the first business day
earlier in time unless it is across a Month boundary, in which
case to take the first business day later in time.
weekmask : str or array_like of bool, optional
A seven-element array indicating which of Monday through Sunday may
be valid business days. May be specified as a list or array, like
[1,1,1,1,1,0,0], a length-seven string like '1111100', or a string
of three-letter weekday names, like 'MonTueWedThuFri'. The latter
string representation is most useful when only one day of the
week is important, like 'Mon' if you want to calculate the date
of Easter.
holidays : array_like of datetime64[D], optional
An array of dates which should be blacked out from being considered
as business days. They may be specified in any order, and NaT
(not-a-time) dates are ignored. Internally, this list is normalized
into a form suited for fast business day calculations.
busdaycal : busdaycalendar, optional
A `busdaycalendar` object which specifies the business days. If this
parameter is provided, neither weekmask nor holidays may be
provided.
out : array of datetime64[D], optional
If provided, this array is filled with the result.

Returns
-------
out : array of datetime64[D]
An array with a shape from broadcasting ``dates`` and ``offsets``
together, containing the dates with offsets applied.

See Also
--------
busdaycalendar: An object for efficiently specifying which are business days.
is_busday : Returns a boolean array indicating valid business days.
busday_count : Counts how many business days are in a half-open date range.

Examples
--------
>>> # First business day in October 2011 (not accounting for holidays)
... np.busday_offset('2011-10', 0, roll='forward')
numpy.datetime64('2011-10-03','D')
>>> # Last business day in February 2012 (not accounting for holidays)
... np.busday_offset('2012-03', -1, roll='forward')
numpy.datetime64('2012-02-29','D')
>>> # Third Wednesday in January 2011
... np.busday_offset('2011-01', 2, roll='forward', weekmask='Wed')
numpy.datetime64('2011-01-19','D')
>>> # 2012 Mother's Day in Canada and the U.S.
... np.busday_offset('2012-05', 1, roll='forward', weekmask='Sun')
numpy.datetime64('2012-05-13','D')

>>> # First business day on or after a date
... np.busday_offset('2011-03-20', 0, roll='forward')
numpy.datetime64('2011-03-21','D')
>>> np.busday_offset('2011-03-22', 0, roll='forward')
numpy.datetime64('2011-03-22','D')
>>> # First business day after a date
... np.busday_offset('2011-03-20', 1, roll='backward')
numpy.datetime64('2011-03-21','D')
>>> np.busday_offset('2011-03-22', 1, roll='backward')
numpy.datetime64('2011-03-23','D')
""")

add_newdoc('numpy.core.multiarray', 'busday_count',
"""
busday_count(begindates, enddates, weekmask='1111100', holidays=[], busdaycal=None, out=None)

Counts the number of business days between `begindates` and
`enddates`, not including the day of `enddates`.

Parameters
----------
begindates : array_like of datetime64[D]
The array of the first dates for counting.
enddates : array_like of datetime64[D]
The array of the end dates for counting, which are excluded
from the count themselves.
weekmask : str or array_like of bool, optional
A seven-element array indicating which of Monday through Sunday may
be valid business days. May be specified as a list or array, like
[1,1,1,1,1,0,0], a length-seven string like '1111100', or a string
of three-letter weekday names, like 'MonTueWedThuFri'. The latter
string representation is most useful when only one day of the
week is important, like 'Mon' if you want to calculate the date
of Easter.
holidays : array_like of datetime64[D], optional
An array of dates which should be blacked out from being considered
as business days. They may be specified in any order, and NaT
(not-a-time) dates are ignored. Internally, this list is normalized
into a form suited for fast business day calculations.
busdaycal : busdaycalendar, optional
A `busdaycalendar` object which specifies the business days. If this
parameter is provided, neither weekmask nor holidays may be
provided.
out : array of int, optional
If provided, this array is filled with the result.

Returns
-------
out : array of int
An array with a shape from broadcasting ``begindates`` and ``enddates``
together, containing the number of business days between
the begin and end dates.

See Also
--------
busdaycalendar: An object for efficiently specifying which are business days.
is_busday : Returns a boolean array indicating valid business days.
busday_offset : Applies an offset counted in business days.

Examples
--------
>>> # Number of weekdays in January 2011
... np.busday_count('2011-01', '2011-02')
21
>>> # Number of weekdays in 2011
... np.busday_count('2011', '2012')
260
>>> # Number of Saturdays in 2011
... np.busday_count('2011', '2012', weekmask='Sat')
53
""")

##############################################################################
#
# nd_grid instances
Expand Down
2 changes: 2 additions & 0 deletions numpy/core/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,8 @@ if ENABLE_SEPARATE_COMPILATION:
pjoin('src', 'multiarray', 'hashdescr.c'),
pjoin('src', 'multiarray', 'arrayobject.c'),
pjoin('src', 'multiarray', 'datetime.c'),
pjoin('src', 'multiarray', 'datetime_busday.c'),
pjoin('src', 'multiarray', 'datetime_busdaycal.c'),
pjoin('src', 'multiarray', 'numpyos.c'),
pjoin('src', 'multiarray', 'flagsobject.c'),
pjoin('src', 'multiarray', 'descriptor.c'),
Expand Down
5 changes: 1 addition & 4 deletions numpy/core/arrayprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,8 +718,5 @@ def __init__(self, data):
self.format = '%' + str(max_str_len) + 'd'

def __call__(self, x):
if _MININT < x < _MAXINT:
return self.format % x.astype('i8')
else:
return "%s" % x
return self.format % x.astype('i8')

2 changes: 2 additions & 0 deletions numpy/core/code_generators/genapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
join('multiarray', 'conversion_utils.c'),
join('multiarray', 'buffer.c'),
join('multiarray', 'datetime.c'),
join('multiarray', 'datetime_busday.c'),
join('multiarray', 'datetime_busdaycal.c'),
join('multiarray', 'nditer.c.src'),
join('multiarray', 'nditer_pywrap.c'),
join('multiarray', 'einsum.c.src'),
Expand Down
1 change: 1 addition & 0 deletions numpy/core/code_generators/generate_umath.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ def english_upper(s):
TD(intfltcmplx),
[TypeDescription('m', FullTypeDescr, 'mq', 'm'),
TypeDescription('m', FullTypeDescr, 'md', 'm'),
TypeDescription('m', FullTypeDescr, 'mm', 'd'),
],
TD(O, f='PyNumber_Divide'),
),
Expand Down
35 changes: 30 additions & 5 deletions numpy/core/include/numpy/ndarraytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,6 @@ typedef enum {
NPY_FR_Y, /* Years */
Copy link
Member

Choose a reason for hiding this comment

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

Could these go in npy_common.h?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, that sounds fine. I'm wanting to rename away from the 'frequency' nomenclature as well.

NPY_FR_M, /* Months */
NPY_FR_W, /* Weeks */
NPY_FR_B, /* Business days (weekdays, doesn't account for holidays) */
NPY_FR_D, /* Days */
NPY_FR_h, /* hours */
NPY_FR_m, /* minutes */
Expand All @@ -243,16 +242,16 @@ typedef enum {
NPY_FR_ns,/* nanoseconds */
NPY_FR_ps,/* picoseconds */
NPY_FR_fs,/* femtoseconds */
NPY_FR_as /* attoseconds */
NPY_FR_as,/* attoseconds */
NPY_FR_GENERIC /* Generic, unbound units, can convert to anything */
} NPY_DATETIMEUNIT;

#define NPY_DATETIME_NUMUNITS (NPY_FR_as + 1)
#define NPY_DATETIME_DEFAULTUNIT NPY_FR_us
#define NPY_DATETIME_NUMUNITS (NPY_FR_GENERIC + 1)
#define NPY_DATETIME_DEFAULTUNIT NPY_FR_GENERIC

#define NPY_STR_Y "Y"
#define NPY_STR_M "M"
#define NPY_STR_W "W"
#define NPY_STR_B "B"
#define NPY_STR_D "D"
#define NPY_STR_h "h"
#define NPY_STR_m "m"
Expand All @@ -264,6 +263,32 @@ typedef enum {
#define NPY_STR_fs "fs"
#define NPY_STR_as "as"

/*
* Business day conventions for mapping invalid business
* days to valid business days.
*/
typedef enum {
/* Go forward in time to the following business day. */
NPY_BUSDAY_FORWARD,
NPY_BUSDAY_FOLLOWING = NPY_BUSDAY_FORWARD,
/* Go backward in time to the preceding business day. */
NPY_BUSDAY_BACKWARD,
NPY_BUSDAY_PRECEDING = NPY_BUSDAY_BACKWARD,
/*
* Go forward in time to the following business day, unless it
* crosses a month boundary, in which case go backward
*/
NPY_BUSDAY_MODIFIEDFOLLOWING,
/*
* Go backward in time to the preceding business day, unless it
* crosses a month boundary, in which case go forward.
*/
NPY_BUSDAY_MODIFIEDPRECEDING,
/* Produce a NaT for non-business days. */
NPY_BUSDAY_NAT,
/* Raise an exception for non-business days. */
NPY_BUSDAY_RAISE
} NPY_BUSDAY_ROLL;

/*
* This is to typedef npy_intp to the appropriate pointer size for
Copy link
Member

Choose a reason for hiding this comment

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

I've moved that into npy_common for the sort library. Looks like I'll need to do some merging ;)

Copy link
Member Author

Choose a reason for hiding this comment

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

I want to do a relatively invasive header shuffle at some point towards managing future ABI compatibility, we'll have to make sure not to step on each others toes with that.

Expand Down
Loading