diff options
author | Mark Wiebe <mwiebe@enthought.com> | 2011-07-19 14:45:59 -0500 |
---|---|---|
committer | Mark Wiebe <mwiebe@enthought.com> | 2011-07-19 14:46:14 -0500 |
commit | ecaf1e1765eb5697a27761b49a25081b1fffb90d (patch) | |
tree | ee10ea7d84cd135f6589a329d35a3a22de5e919e | |
parent | c649139121015e3d6bb82377e3c9094a0f850065 (diff) | |
parent | 1d3add610afc367d59bdc0c40a16cacf766a48a9 (diff) | |
download | numpy-ecaf1e1765eb5697a27761b49a25081b1fffb90d.tar.gz |
MRG: Merge branch 'steveha/datetime64_doc'
-rw-r--r-- | doc/source/reference/arrays.datetime.rst | 122 | ||||
-rw-r--r-- | numpy/add_newdocs.py | 175 | ||||
-rw-r--r-- | numpy/core/src/multiarray/datetime_busdaycal.c | 123 | ||||
-rw-r--r-- | numpy/core/tests/test_datetime.py | 20 |
4 files changed, 274 insertions, 166 deletions
diff --git a/doc/source/reference/arrays.datetime.rst b/doc/source/reference/arrays.datetime.rst index 2fd6dfcdd..541f97884 100644 --- a/doc/source/reference/arrays.datetime.rst +++ b/doc/source/reference/arrays.datetime.rst @@ -23,7 +23,7 @@ be either a :ref:`date unit <arrays.dtypes.dateunits>` or a :ref:`time unit <arrays.dtypes.timeunits>`. The date units are years ('Y'), months ('M'), weeks ('W'), and days ('D'), while the time units are hours ('h'), minutes ('m'), seconds ('s'), milliseconds ('ms'), and -more SI-prefix seconds-based units. +some additional SI-prefix seconds-based units. .. admonition:: Example @@ -139,7 +139,7 @@ simple datetime calculations. >>> np.timedelta64(1,'W') / np.timedelta64(1,'D') 7.0 -There are two Timedelta units, years and months, which are treated +There are two Timedelta units ('Y', years and 'M', months) which are treated specially, because how much time they represent changes depending on when they are used. While a timedelta day unit is equivalent to 24 hours, there is no way to convert a month unit into days, because @@ -167,7 +167,13 @@ other units based on input data. Datetimes are always stored based on POSIX time (though having a TAI mode which allows for accounting of leap-seconds is proposed), with a epoch of 1970-01-01T00:00Z. This means the supported dates are -always a symmetric interval around 1970. +always a symmetric interval around the epoch, called "time span" in the +table below. + +The length of the span is the range of a 64-bit integer times the length +of the date or unit. For example, the time span for 'W' (week) is exactly +7 times longer than the time span for 'D' (day), and the time span for +'D' (day) is exactly 24 times longer than the time span for 'h' (hour). Here are the date units: @@ -176,10 +182,10 @@ Here are the date units: ======== ================ ======================= ========================== Code Meaning Time span (relative) Time span (absolute) ======== ================ ======================= ========================== - Y year +- 9.2e18 years [9.2e18 BC, 9.2e18 AD] - M month +- 7.6e17 years [7.6e17 BC, 7.6e17 AD] - W week +- 1.7e17 years [1.7e17 BC, 1.7e17 AD] - D day +- 2.5e16 years [2.5e16 BC, 2.5e16 AD] + Y year +/- 9.2e18 years [9.2e18 BC, 9.2e18 AD] + M month +/- 7.6e17 years [7.6e17 BC, 7.6e17 AD] + W week +/- 1.7e17 years [1.7e17 BC, 1.7e17 AD] + D day +/- 2.5e16 years [2.5e16 BC, 2.5e16 AD] ======== ================ ======================= ========================== And here are the time units: @@ -189,28 +195,34 @@ And here are the time units: ======== ================ ======================= ========================== Code Meaning Time span (relative) Time span (absolute) ======== ================ ======================= ========================== - h hour +- 1.0e15 years [1.0e15 BC, 1.0e15 AD] - m minute +- 1.7e13 years [1.7e13 BC, 1.7e13 AD] - s second +- 2.9e12 years [ 2.9e9 BC, 2.9e9 AD] - ms millisecond +- 2.9e9 years [ 2.9e6 BC, 2.9e6 AD] - us microsecond +- 2.9e6 years [290301 BC, 294241 AD] - ns nanosecond +- 292 years [ 1678 AD, 2262 AD] - ps picosecond +- 106 days [ 1969 AD, 1970 AD] - fs femtosecond +- 2.6 hours [ 1969 AD, 1970 AD] - as attosecond +- 9.2 seconds [ 1969 AD, 1970 AD] + h hour +/- 1.0e15 years [1.0e15 BC, 1.0e15 AD] + m minute +/- 1.7e13 years [1.7e13 BC, 1.7e13 AD] + s second +/- 2.9e12 years [ 2.9e9 BC, 2.9e9 AD] + ms millisecond +/- 2.9e9 years [ 2.9e6 BC, 2.9e6 AD] + us microsecond +/- 2.9e6 years [290301 BC, 294241 AD] + ns nanosecond +/- 292 years [ 1678 AD, 2262 AD] + ps picosecond +/- 106 days [ 1969 AD, 1970 AD] + fs femtosecond +/- 2.6 hours [ 1969 AD, 1970 AD] + as attosecond +/- 9.2 seconds [ 1969 AD, 1970 AD] ======== ================ ======================= ========================== Business Day Functionality ========================== -To allow the datetime to be used in contexts where accounting for weekends -and holidays is important, NumPy includes a set of functions for -working with business days. +To allow the datetime to be used in contexts where only certain days of +the week are valid, NumPy includes a set of "busday" (business day) +functions. + +The default for busday functions is that the only valid days are Monday +through Friday (the usual business days). The implementation is based on +a "weekmask" containing 7 Boolean flags to indicate valid days; custom +weekmasks are possible that specify other sets of valid days. + +The "busday" functions can additionally check a list of "holiday" dates, +specific dates that are not valid days. The function :func:`busday_offset` allows you to apply offsets -specified in business days to datetimes with a unit of 'day'. By default, -a business date is defined to be any date which falls on Monday through -Friday, but this can be customized with a weekmask and a list of holidays. +specified in business days to datetimes with a unit of 'D' (day). .. admonition:: Example @@ -266,7 +278,7 @@ is necessary to get a desired answer. The function is also useful for computing some kinds of days like holidays. In Canada and the U.S., Mother's day is on -the second Sunday in May, which can be computed with a special +the second Sunday in May, which can be computed with a custom weekmask. .. admonition:: Example @@ -274,11 +286,67 @@ weekmask. >>> np.busday_offset('2012-05', 1, roll='forward', weekmask='Sun') numpy.datetime64('2012-05-13','D') -When performance is important for manipulating many business date +When performance is important for manipulating many business dates with one particular choice of weekmask and holidays, there is an object :class:`busdaycalendar` which stores the data necessary in an optimized form. -The other two functions for business days are :func:`is_busday` -and :func:`busday_count`, which are more straightforward and -not explained here. +np.is_busday(): +``````````````` +To test a datetime64 value to see if it is a valid day, use :func:`is_busday`. + +.. admonition:: Example + + >>> np.is_busday(np.datetime64('2011-07-15')) # a Friday + True + >>> np.is_busday(np.datetime64('2011-07-16')) # a Saturday + False + >>> np.is_busday(np.datetime64('2011-07-16'), weekmask="Sat Sun") + True + >>> a = np.arange(np.datetime64('2011-07-11'), np.datetime64('2011-07-18')) + >>> np.is_busday(a) + array([ True, True, True, True, True, False, False], dtype='bool') + +np.busday_count(): +`````````````````` +To find how many valid days there are in a specified range of datetime64 +dates, use :func:`busday_count`: + +.. admonition:: Example + + >>> np.busday_count(np.datetime64('2011-07-11'), np.datetime64('2011-07-18')) + 5 + >>> np.busday_count(np.datetime64('2011-07-18'), np.datetime64('2011-07-11')) + 0 + # note: In future this will likely return -5, not 0 + +If you have an array of datetime64 day values, and you want a count of +how many of them are valid dates, you can do this: + +.. admonition:: Example + + >>> a = np.arange(np.datetime64('2011-07-11'), np.datetime64('2011-07-18')) + >>> np.count_nonzero(np.is_busday(a)) + 5 + + + +Custom Weekmasks +---------------- + +Here are several examples of custom weekmask values. These examples +specify the "busday" default of Monday through Friday being valid days. + +Some examples:: + + # Positional sequences; positions are Monday through Sunday. + # Length of the sequence must be exactly 7. + weekmask = [1, 1, 1, 1, 1, 0, 0] + # list or other sequence; 0 == invalid day, 1 == valid day + weekmask = "1111100" + # string '0' == invalid day, '1' == valid day + + # string abbreviations from this list: Mon Tue Wed Thu Fri Sat Sun + weekmask = "Mon Tue Wed Thu Fri" + # any amount of whitespace is allowed; abbreviations are case-sensitive. + weekmask = "MonTue Wed Thu\tFri" diff --git a/numpy/add_newdocs.py b/numpy/add_newdocs.py index 1e1d237a4..64f2f436a 100644 --- a/numpy/add_newdocs.py +++ b/numpy/add_newdocs.py @@ -5993,44 +5993,52 @@ 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. + A business day calendar object that efficiently stores information + defining valid days for the busday family of functions. + + The default valid days are Monday through Friday ("business days"). + A busdaycalendar object can be specified with any set of weekly + valid days, plus an optional "holiday" dates that always will be invalid. + + Once a busdaycalendar object is created, the weekmask and holidays + cannot be modified. .. versionadded:: 1.7.0 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. + A seven-element array indicating which of Monday through Sunday are + valid days. May be specified as a length-seven list or array, like + [1,1,1,1,1,0,0]; a length-seven string, like '1111100'; or a string + like "Mon Tue Wed Thu Fri", made up of 3-character abbreviations for + weekdays, optionally separated by white space. Valid abbreviations + are: Mon Tue Wed Thu Fri Sat Sun 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. + An array of dates to consider as invalid dates, no matter which + weekday they fall upon. Holiday dates may be specified in any + order, and NaT (not-a-time) dates are ignored. This list is + saved in a normalized form that is suited for fast calculations + of valid days. Returns ------- out : busdaycalendar A business day calendar object containing the specified - weekmask and holidays. + weekmask and holidays values. 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. + is_busday : Returns a boolean array indicating valid days. + busday_offset : Applies an offset counted in valid days. + busday_count : Counts how many valid days are in a half-open date range. Attributes ---------- - weekmask : seven-element array of bool - holidays : sorted array of datetime64[D] + Note: once a busdaycalendar object is created, you cannot modify the + weekmask or holidays. The attributes return copies of internal data. + weekmask : (copy) seven-element array of bool + holidays : (copy) sorted array of datetime64[D] Examples -------- @@ -6046,17 +6054,16 @@ add_newdoc('numpy.core.multiarray', 'busdaycalendar', """) add_newdoc('numpy.core.multiarray', 'busdaycalendar', ('weekmask', - """A copy of the seven-element boolean mask indicating valid business days.""")) + """A copy of the seven-element boolean mask indicating valid days.""")) add_newdoc('numpy.core.multiarray', 'busdaycalendar', ('holidays', - """A copy of the holiday array indicating blacked out business days.""")) + """A copy of the holiday array indicating additional invalid 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. + Calculates which of the given dates are valid days, and which are not. .. versionadded:: 1.7.0 @@ -6065,20 +6072,19 @@ add_newdoc('numpy.core.multiarray', 'is_busday', 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. + A seven-element array indicating which of Monday through Sunday are + valid days. May be specified as a length-seven list or array, like + [1,1,1,1,1,0,0]; a length-seven string, like '1111100'; or a string + like "Mon Tue Wed Thu Fri", made up of 3-character abbreviations for + weekdays, optionally separated by white space. Valid abbreviations + are: Mon Tue Wed Thu Fri Sat Sun 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. + An array of dates to consider as invalid dates. They may be + specified in any order, and NaT (not-a-time) dates are ignored. + This list is saved in a normalized form that is suited for + fast calculations of valid days. busdaycal : busdaycalendar, optional - A `busdaycalendar` object which specifies the business days. If this + A `busdaycalendar` object which specifies the valid days. If this parameter is provided, neither weekmask nor holidays may be provided. out : array of bool, optional @@ -6088,13 +6094,13 @@ add_newdoc('numpy.core.multiarray', 'is_busday', ------- out : array of bool An array with the same shape as ``dates``, containing True for - each valid business day, and False for the others. + each valid day, and False for each invalid day. 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. + busdaycalendar: An object that specifies a custom set of valid days. + busday_offset : Applies an offset counted in valid days. + busday_count : Counts how many valid days are in a half-open date range. Examples -------- @@ -6108,9 +6114,9 @@ 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 + First adjusts the date to fall on a valid day according to the ``roll`` rule, then applies offsets to the given dates - counted in business days. + counted in valid days. .. versionadded:: 1.7.0 @@ -6121,36 +6127,35 @@ add_newdoc('numpy.core.multiarray', 'busday_offset', 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 + How to treat dates that do not fall on a valid 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 + * 'raise' means to raise an exception for an invalid day. + * 'nat' means to return a NaT (not-a-time) for an invalid day. + * 'forward' and 'following' mean to take the first valid day later in time. - * 'backward' and 'preceding' mean to take the first business day + * 'backward' and 'preceding' mean to take the first valid day earlier in time. - * 'modifiedfollowing' means to take the first business day + * 'modifiedfollowing' means to take the first valid 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 + case to take the first valid day earlier in time. + * 'modifiedpreceding' means to take the first valid day earlier in time unless it is across a Month boundary, in which - case to take the first business day later in time. + case to take the first valid 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. + A seven-element array indicating which of Monday through Sunday are + valid days. May be specified as a length-seven list or array, like + [1,1,1,1,1,0,0]; a length-seven string, like '1111100'; or a string + like "Mon Tue Wed Thu Fri", made up of 3-character abbreviations for + weekdays, optionally separated by white space. Valid abbreviations + are: Mon Tue Wed Thu Fri Sat Sun 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. + An array of dates to consider as invalid dates. They may be + specified in any order, and NaT (not-a-time) dates are ignored. + This list is saved in a normalized form that is suited for + fast calculations of valid days. busdaycal : busdaycalendar, optional - A `busdaycalendar` object which specifies the business days. If this + A `busdaycalendar` object which specifies the valid days. If this parameter is provided, neither weekmask nor holidays may be provided. out : array of datetime64[D], optional @@ -6164,9 +6169,9 @@ add_newdoc('numpy.core.multiarray', 'busday_offset', 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. + busdaycalendar: An object that specifies a custom set of valid days. + is_busday : Returns a boolean array indicating valid days. + busday_count : Counts how many valid days are in a half-open date range. Examples -------- @@ -6199,9 +6204,14 @@ 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 + Counts the number of valid days between `begindates` and `enddates`, not including the day of `enddates`. + If ``enddates`` specifies a date value that is earlier than the + corresponding ``begindates`` date value, the count will be 0. + However, in future this may change to a negative count of valid + days. + .. versionadded:: 1.7.0 Parameters @@ -6212,20 +6222,19 @@ add_newdoc('numpy.core.multiarray', 'busday_count', 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. + A seven-element array indicating which of Monday through Sunday are + valid days. May be specified as a length-seven list or array, like + [1,1,1,1,1,0,0]; a length-seven string, like '1111100'; or a string + like "Mon Tue Wed Thu Fri", made up of 3-character abbreviations for + weekdays, optionally separated by white space. Valid abbreviations + are: Mon Tue Wed Thu Fri Sat Sun 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. + An array of dates to consider as invalid dates. They may be + specified in any order, and NaT (not-a-time) dates are ignored. + This list is saved in a normalized form that is suited for + fast calculations of valid days. busdaycal : busdaycalendar, optional - A `busdaycalendar` object which specifies the business days. If this + A `busdaycalendar` object which specifies the valid days. If this parameter is provided, neither weekmask nor holidays may be provided. out : array of int, optional @@ -6235,14 +6244,14 @@ add_newdoc('numpy.core.multiarray', 'busday_count', ------- out : array of int An array with a shape from broadcasting ``begindates`` and ``enddates`` - together, containing the number of business days between + together, containing the number of valid 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. + busdaycalendar: An object that specifies a custom set of valid days. + is_busday : Returns a boolean array indicating valid days. + busday_offset : Applies an offset counted in valid days. Examples -------- diff --git a/numpy/core/src/multiarray/datetime_busdaycal.c b/numpy/core/src/multiarray/datetime_busdaycal.c index ae35212ea..018912ee8 100644 --- a/numpy/core/src/multiarray/datetime_busdaycal.c +++ b/numpy/core/src/multiarray/datetime_busdaycal.c @@ -46,6 +46,7 @@ PyArray_WeekMaskConverter(PyObject *weekmask_in, npy_bool *weekmask) if (PyBytes_Check(obj)) { char *str; Py_ssize_t len; + int i; if (PyBytes_AsStringAndSize(obj, &str, &len) < 0) { Py_DECREF(obj); @@ -54,7 +55,6 @@ PyArray_WeekMaskConverter(PyObject *weekmask_in, npy_bool *weekmask) /* Length 7 is a string like "1111100" */ if (len == 7) { - int i; for (i = 0; i < 7; ++i) { switch(str[i]) { case '0': @@ -64,70 +64,81 @@ PyArray_WeekMaskConverter(PyObject *weekmask_in, npy_bool *weekmask) weekmask[i] = 1; break; default: - goto invalid_weekmask_string; + goto general_weekmask_string; } } goto finish; } - /* Length divisible by 3 is a string like "Mon" or "MonWedFri" */ - else if (len % 3 == 0) { - int i; - memset(weekmask, 0, 7); - for (i = 0; i < len; i += 3) { - switch (str[i]) { - case 'M': - if (str[i+1] == 'o' && str[i+2] == 'n') { - weekmask[0] = 1; - } - else { - goto invalid_weekmask_string; - } - break; - case 'T': - if (str[i+1] == 'u' && str[i+2] == 'e') { - weekmask[1] = 1; - } - else if (str[i+1] == 'h' && str[i+2] == 'u') { - weekmask[3] = 1; - } - else { - goto invalid_weekmask_string; - } - break; - case 'W': - if (str[i+1] == 'e' && str[i+2] == 'd') { - weekmask[2] = 1; - } - else { - goto invalid_weekmask_string; - } - break; - case 'F': - if (str[i+1] == 'r' && str[i+2] == 'i') { - weekmask[4] = 1; - } - else { - goto invalid_weekmask_string; - } - break; - case 'S': - if (str[i+1] == 'a' && str[i+2] == 't') { - weekmask[5] = 1; - } - else if (str[i+1] == 'u' && str[i+2] == 'n') { - weekmask[6] = 1; - } - else { - goto invalid_weekmask_string; - } - break; - } + +general_weekmask_string: + /* a string like "SatSun" or "Mon Tue Wed" */ + memset(weekmask, 0, 7); + for (i = 0; i < len; i += 3) { + while (isspace(str[i])) + ++i; + + if (i == len) { + goto finish; + } + else if (i + 2 >= len) { + goto invalid_weekmask_string; } - goto finish; + switch (str[i]) { + case 'M': + if (str[i+1] == 'o' && str[i+2] == 'n') { + weekmask[0] = 1; + } + else { + goto invalid_weekmask_string; + } + break; + case 'T': + if (str[i+1] == 'u' && str[i+2] == 'e') { + weekmask[1] = 1; + } + else if (str[i+1] == 'h' && str[i+2] == 'u') { + weekmask[3] = 1; + } + else { + goto invalid_weekmask_string; + } + break; + case 'W': + if (str[i+1] == 'e' && str[i+2] == 'd') { + weekmask[2] = 1; + } + else { + goto invalid_weekmask_string; + } + break; + case 'F': + if (str[i+1] == 'r' && str[i+2] == 'i') { + weekmask[4] = 1; + } + else { + goto invalid_weekmask_string; + } + break; + case 'S': + if (str[i+1] == 'a' && str[i+2] == 't') { + weekmask[5] = 1; + } + else if (str[i+1] == 'u' && str[i+2] == 'n') { + weekmask[6] = 1; + } + else { + goto invalid_weekmask_string; + } + break; + default: + goto invalid_weekmask_string; + } } + goto finish; + invalid_weekmask_string: PyErr_Format(PyExc_ValueError, "Invalid business day weekmask string \"%s\"", diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index 2770364f0..563f9e87c 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -1440,8 +1440,28 @@ class TestDateTime(TestCase): # Default M-F weekmask assert_equal(bdd.weekmask, np.array([1,1,1,1,1,0,0], dtype='?')) + # Check string weekmask with varying whitespace. + bdd = np.busdaycalendar(weekmask="Sun TueWed Thu\tFri") + assert_equal(bdd.weekmask, np.array([0,1,1,1,1,0,1], dtype='?')) + + # Check length 7 0/1 string + bdd = np.busdaycalendar(weekmask="0011001") + assert_equal(bdd.weekmask, np.array([0,0,1,1,0,0,1], dtype='?')) + + # Check length 7 string weekmask. + bdd = np.busdaycalendar(weekmask="Mon Tue") + assert_equal(bdd.weekmask, np.array([1,1,0,0,0,0,0], dtype='?')) + # All-zeros weekmask should raise assert_raises(ValueError, np.busdaycalendar, weekmask=[0,0,0,0,0,0,0]) + # weekday names must be correct case + assert_raises(ValueError, np.busdaycalendar, weekmask="satsun") + # All-zeros weekmask should raise + assert_raises(ValueError, np.busdaycalendar, weekmask="") + # Invalid weekday name codes should raise + assert_raises(ValueError, np.busdaycalendar, weekmask="Mon Tue We") + assert_raises(ValueError, np.busdaycalendar, weekmask="Max") + assert_raises(ValueError, np.busdaycalendar, weekmask="Monday Tue") def test_datetime_busday_holidays_offset(self): # With exactly one holiday |