diff options
author | Mark Wiebe <mwiebe@enthought.com> | 2011-06-08 17:56:25 -0500 |
---|---|---|
committer | Mark Wiebe <mwiebe@enthought.com> | 2011-06-09 12:04:06 -0500 |
commit | d6c63e31c8761bff897b4bdf8146aa5704ada0f9 (patch) | |
tree | 2afcc7db11e01f48c71f7aa46ea5e4f8f92cacdb | |
parent | 50261be60dba090c65ee88c1531fb00a532db17a (diff) | |
download | numpy-d6c63e31c8761bff897b4bdf8146aa5704ada0f9.tar.gz |
ENH: datetime-meta: Add generic units as a datetime unit type
This allows integers to convert into timedeltas without binding
to a default unit, so that later when it's combined with another
data type it adopts that type instead of overriding it haphazardly.
This makes things generally more intuitive.
-rw-r--r-- | numpy/core/include/numpy/ndarraytypes.h | 7 | ||||
-rw-r--r-- | numpy/core/src/multiarray/datetime.c | 166 | ||||
-rw-r--r-- | numpy/core/src/multiarray/dtype_transfer.c | 10 | ||||
-rw-r--r-- | numpy/core/src/multiarray/scalartypes.c.src | 9 | ||||
-rw-r--r-- | numpy/core/tests/test_datetime.py | 133 |
5 files changed, 215 insertions, 110 deletions
diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h index 5bed8d70c..7d04c0106 100644 --- a/numpy/core/include/numpy/ndarraytypes.h +++ b/numpy/core/include/numpy/ndarraytypes.h @@ -243,11 +243,12 @@ 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" diff --git a/numpy/core/src/multiarray/datetime.c b/numpy/core/src/multiarray/datetime.c index a8970dc7b..cb28906c1 100644 --- a/numpy/core/src/multiarray/datetime.c +++ b/numpy/core/src/multiarray/datetime.c @@ -27,10 +27,6 @@ numpy_pydatetime_import() static int is_leapyear(npy_int64 year); - -/* For defaults and errors */ -#define NPY_FR_ERR -1 - /* Exported as DATETIMEUNITS in multiarraymodule.c */ NPY_NO_EXPORT char *_datetime_strings[] = { NPY_STR_Y, @@ -46,7 +42,8 @@ NPY_NO_EXPORT char *_datetime_strings[] = { NPY_STR_ns, NPY_STR_ps, NPY_STR_fs, - NPY_STR_as + NPY_STR_as, + "generic" }; /* @@ -251,6 +248,14 @@ convert_datetimestruct_to_datetime(PyArray_DatetimeMetaData *meta, return 0; } + /* Cannot instantiate a datetime with generic units */ + if (meta->base == NPY_FR_GENERIC) { + PyErr_SetString(PyExc_ValueError, + "Cannot create a NumPy datetime other than NaT " + "with generic units"); + return -1; + } + if (dts->event < 0 || dts->event >= meta->events) { PyErr_Format(PyExc_ValueError, "NumPy datetime event %d is outside range [0,%d)", @@ -545,6 +550,14 @@ convert_datetime_to_datetimestruct(PyArray_DatetimeMetaData *meta, out->year = NPY_DATETIME_NAT; return 0; } + + /* Datetimes can't be in generic units */ + if (meta->base == NPY_FR_GENERIC) { + PyErr_SetString(PyExc_ValueError, + "Cannot convert a NumPy datetime value other than NaT " + "with generic units"); + return -1; + } /* Extract the event number */ if (meta->events > 1) { @@ -1101,6 +1114,15 @@ parse_datetime_metadata_from_metastr(char *metastr, Py_ssize_t len, { char *substr = metastr, *substrend = NULL; + /* Treat the empty string as generic units */ + if (len == 0) { + out_meta->base = NPY_FR_GENERIC; + out_meta->num = 1; + out_meta->events = 1; + + return 0; + } + /* The metadata string must start with a '[' */ if (len < 3 || *substr++ != '[') { goto bad_input; @@ -1313,6 +1335,12 @@ convert_datetime_divisor_to_multiple(PyArray_DatetimeMetaData *meta, NPY_DATETIMEUNIT *baseunit; int q, r; + if (meta->base == NPY_FR_GENERIC) { + PyErr_SetString(PyExc_ValueError, + "Can't use 'den' divisor with generic units"); + return -1; + } + ind = ((int)meta->base - (int)NPY_FR_Y)*2; totry = _multiples_table[ind]; baseunit = _multiples_table[ind + 1]; @@ -1330,10 +1358,10 @@ convert_datetime_divisor_to_multiple(PyArray_DatetimeMetaData *meta, baseunit = _multiples_table[ind + 1]; baseunit[0] = meta->base + 1; baseunit[1] = meta->base + 2; - if (meta->base == NPY_DATETIME_NUMUNITS - 2) { + if (meta->base == NPY_FR_as - 1) { num = 1; } - if (meta->base == NPY_DATETIME_NUMUNITS - 1) { + if (meta->base == NPY_FR_as) { num = 0; } } @@ -1383,12 +1411,14 @@ _datetime_factors[] = { 1000, 1000, 1000, - 1 /* Attoseconds are the smallest base unit */ + 1, /* Attoseconds are the smallest base unit */ + 0 /* Generic units don't have a conversion */ }; /* * Returns the scale factor between the units. Does not validate - * that bigbase represents larger units than littlebase. + * that bigbase represents larger units than littlebase, or that + * the units are not generic. * * Returns 0 if there is an overflow. */ @@ -1451,6 +1481,25 @@ get_datetime_conversion_factor(PyArray_DatetimeMetaData *src_meta, int src_base, dst_base, swapped; npy_uint64 num = 1, denom = 1, tmp, gcd; + /* Generic units change to the destination with no conversion factor */ + if (src_meta->base == NPY_FR_GENERIC) { + *out_num = 1; + *out_denom = 1; + return; + } + /* + * Converting to a generic unit from something other than a generic + * unit is an error. + */ + else if (dst_meta->base == NPY_FR_GENERIC) { + PyErr_SetString(PyExc_ValueError, + "Cannot convert from specific units to generic " + "units in NumPy datetimes or timedeltas"); + *out_num = 0; + *out_denom = 0; + return; + } + if (src_meta->base <= dst_meta->base) { src_base = src_meta->base; dst_base = dst_meta->base; @@ -1503,6 +1552,11 @@ get_datetime_conversion_factor(PyArray_DatetimeMetaData *src_meta, /* If something overflowed, make both num and denom 0 */ if (denom == 0) { + PyErr_Format(PyExc_OverflowError, + "Integer overflow getting a conversion factor between " + "NumPy datetime unit %s and %s", + _datetime_strings[src_base], + _datetime_strings[dst_base]); *out_num = 0; *out_denom = 0; return; @@ -1556,6 +1610,15 @@ datetime_metadata_divides( return 0; } + /* Generic units divide into anything */ + if (meta2->base == NPY_FR_GENERIC) { + return 1; + } + /* Non-generic units never divide into generic units */ + else if (meta1->base == NPY_FR_GENERIC) { + return 0; + } + /* Events must match */ if (meta1->events != meta2->events) { return 0; @@ -1652,6 +1715,16 @@ compute_datetime_metadata_greatest_common_divisor( npy_uint64 num1, num2, num; int events = 1; + /* If either unit is generic, adopt the metadata from the other one */ + if (meta1->base == NPY_FR_GENERIC) { + *out_meta = *meta2; + return 0; + } + else if (meta2->base == NPY_FR_GENERIC) { + *out_meta = *meta1; + return 0; + } + /* Take the maximum of the events */ if (meta1->events > meta2->events) { events = meta1->events; @@ -1918,6 +1991,8 @@ datetime_type_promotion(PyArray_Descr *type1, PyArray_Descr *type2) * a date time unit enum value. The 'metastr' parameter * is used for error messages, and may be NULL. * + * Generic units have no representation as a string in this form. + * * Returns 0 on success, -1 on failure. */ NPY_NO_EXPORT NPY_DATETIMEUNIT @@ -2173,6 +2248,18 @@ append_metastr_to_string(PyArray_DatetimeMetaData *meta, return NULL; } + if (meta->base == NPY_FR_GENERIC) { + /* Without brackets, give a string "generic" */ + if (skip_brackets) { + PyUString_ConcatAndDel(&ret, PyUString_FromString("generic")); + return ret; + } + /* But with brackets, append nothing */ + else { + return ret; + } + } + num = meta->num; events = meta->events; if (meta->base >= 0 && meta->base < NPY_DATETIME_NUMUNITS) { @@ -2349,14 +2436,13 @@ parse_iso_8601_date(char *str, int len, /* * Indicate that this was a special value, and - * recommend 'Y' as the unit because when promoted - * with any other unit, will produce that unit. + * recommend generic units. */ if (out_local != NULL) { *out_local = 0; } if (out_bestunit != NULL) { - *out_bestunit = NPY_FR_Y; + *out_bestunit = NPY_FR_GENERIC; } if (out_special != NULL) { *out_special = 1; @@ -2365,6 +2451,13 @@ parse_iso_8601_date(char *str, int len, return 0; } + if (unit == NPY_FR_GENERIC) { + PyErr_SetString(PyExc_ValueError, + "Cannot create a NumPy datetime other than NaT " + "with generic units"); + return -1; + } + /* * The string "today" resolves to midnight of today's local date in UTC. * This is perhaps a little weird, but done so that further truncation @@ -2943,6 +3036,9 @@ get_datetime_iso_8601_strlen(int local, NPY_DATETIMEUNIT base) } switch (base) { + /* Generic units can only be used to represent NaT */ + case NPY_FR_GENERIC: + return 4; case NPY_FR_as: len += 3; /* "###" */ case NPY_FR_fs: @@ -3013,8 +3109,8 @@ make_iso_8601_date(npy_datetimestruct *dts, char *outstr, int outlen, char *substr = outstr, sublen = outlen; int tmplen; - /* Handle NaT */ - if (dts->year == NPY_DATETIME_NAT) { + /* Handle NaT, and treat a datetime with generic units as NaT */ + if (dts->year == NPY_DATETIME_NAT || base == NPY_FR_GENERIC) { if (outlen < 4) { goto string_too_short; } @@ -3728,7 +3824,7 @@ convert_pyobject_to_datetime(PyArray_DatetimeMetaData *meta, PyObject *obj, /* Do no conversion on raw integers */ else if (PyInt_Check(obj) || PyLong_Check(obj)) { /* Don't allow conversion from an integer without specifying a unit */ - if (meta->base == -1) { + if (meta->base == -1 || meta->base == NPY_FR_GENERIC) { PyErr_SetString(PyExc_ValueError, "Converting an integer to a " "NumPy datetime requires a specified unit"); return -1; @@ -3851,18 +3947,7 @@ convert_pyobject_to_timedelta(PyArray_DatetimeMetaData *meta, PyObject *obj, npy_timedelta *out) { /* Do no conversion on raw integers */ - if (PyInt_Check(obj)) { - /* Use the default unit if none was specified */ - if (meta->base == -1) { - meta->base = NPY_DATETIME_DEFAULTUNIT; - meta->num = 1; - meta->events = 1; - } - - *out = PyInt_AS_LONG(obj); - return 0; - } - else if (PyLong_Check(obj)) { + if (PyInt_Check(obj) || PyLong_Check(obj)) { /* Use the default unit if none was specified */ if (meta->base == -1) { meta->base = NPY_DATETIME_DEFAULTUNIT; @@ -4008,8 +4093,8 @@ convert_datetime_to_pyobject(npy_datetime dt, PyArray_DatetimeMetaData *meta) PyObject *ret = NULL, *tup = NULL; npy_datetimestruct dts; - /* Handle not-a-time */ - if (dt == NPY_DATETIME_NAT) { + /* Handle not-a-time, and generic units as NaT as well */ + if (dt == NPY_DATETIME_NAT || meta->base == NPY_FR_GENERIC) { return PyUString_FromString("NaT"); } @@ -4089,13 +4174,14 @@ convert_timedelta_to_pyobject(npy_timedelta td, PyArray_DatetimeMetaData *meta) } /* - * If the type's precision is greater than microseconds or is - * Y/M/B (nonlinear units), return an int + * If the type's precision is greater than microseconds, is + * Y/M/B (nonlinear units), or is generic units, return an int */ if (meta->base > NPY_FR_us || meta->base == NPY_FR_Y || meta->base == NPY_FR_M || - meta->base == NPY_FR_B) { + meta->base == NPY_FR_B || + meta->base == NPY_FR_GENERIC) { /* Skip use of a tuple for the events, just return the raw int */ return PyLong_FromLongLong(td); } @@ -4215,6 +4301,11 @@ has_equivalent_datetime_metadata(PyArray_Descr *type1, PyArray_Descr *type2) return 0; } + /* For generic units, the num and events are ignored */ + if (meta1->base == NPY_FR_GENERIC && meta2->base == NPY_FR_GENERIC) { + return 1; + } + return meta1->base == meta2->base && meta1->num == meta2->num && meta1->events == meta2->events; @@ -4285,9 +4376,6 @@ cast_timedelta_to_timedelta(PyArray_DatetimeMetaData *src_meta, get_datetime_conversion_factor(src_meta, dst_meta, &num, &denom); if (num == 0) { - PyErr_SetString(PyExc_OverflowError, - "Integer overflow getting a conversion factor between " - "different timedelta types"); return -1; } @@ -4361,7 +4449,7 @@ NPY_NO_EXPORT PyObject * datetime_arange(PyObject *start, PyObject *stop, PyObject *step, PyArray_Descr *dtype) { - PyArray_DatetimeMetaData meta_value, meta_step; + PyArray_DatetimeMetaData meta_value; int is_timedelta = 0; /* * Both datetime and timedelta are stored as int64, so they can @@ -4497,7 +4585,7 @@ datetime_arange(PyObject *start, PyObject *stop, PyObject *step, /* Merge the metadata */ if (compute_datetime_metadata_greatest_common_divisor( &meta_tmp1, &meta_tmp2, - &meta_value, 1) < 0) { + &meta_value, 0, 1) < 0) { return NULL; } @@ -4549,7 +4637,7 @@ datetime_arange(PyObject *start, PyObject *stop, PyObject *step, /* Merge the metadata */ if (compute_datetime_metadata_greatest_common_divisor( &meta_tmp1, &meta_tmp2, - &meta_value, 0) < 0) { + &meta_value, 0, 0) < 0) { return NULL; } @@ -4627,7 +4715,7 @@ datetime_arange(PyObject *start, PyObject *stop, PyObject *step, /* Merge the metadata */ if (compute_datetime_metadata_greatest_common_divisor( &meta_tmp1, &meta_tmp2, - &meta_value, 1) < 0) { + &meta_value, 1, 1) < 0) { return NULL; } diff --git a/numpy/core/src/multiarray/dtype_transfer.c b/numpy/core/src/multiarray/dtype_transfer.c index 14a6c9d6a..8d53a4b65 100644 --- a/numpy/core/src/multiarray/dtype_transfer.c +++ b/numpy/core/src/multiarray/dtype_transfer.c @@ -868,16 +868,6 @@ get_nbo_cast_datetime_transfer_function(int aligned, get_datetime_conversion_factor(src_meta, dst_meta, &num, &denom); if (num == 0) { - PyObject *errmsg; - errmsg = PyUString_FromString("Integer overflow " - "getting a conversion factor between types "); - PyUString_ConcatAndDel(&errmsg, - PyObject_Repr((PyObject *)src_dtype)); - PyUString_ConcatAndDel(&errmsg, - PyUString_FromString(" and ")); - PyUString_ConcatAndDel(&errmsg, - PyObject_Repr((PyObject *)dst_dtype)); - PyErr_SetObject(PyExc_OverflowError, errmsg); return NPY_FAIL; } diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src index 50e51e591..49ac76441 100644 --- a/numpy/core/src/multiarray/scalartypes.c.src +++ b/numpy/core/src/multiarray/scalartypes.c.src @@ -701,7 +701,8 @@ static char *_datetime_verbose_strings[] = { "nanoseconds", "picoseconds", "femtoseconds", - "attoseconds" + "attoseconds", + "generic time units" }; static PyObject * @@ -2492,6 +2493,7 @@ finish: * #name = datetime, timedelta# * #Name = Datetime, Timedelta# * #NAME = DATETIME, TIMEDELTA# + * #is_datetime = 1, 0# */ static PyObject * @@ -2535,7 +2537,12 @@ static PyObject * ret->obmeta.events = 1; } + /* Make datetime default to NaT, timedelta default to zero */ +#if @is_datetime@ + ret->obval = NPY_DATETIME_NAT; +#else ret->obval = 0; +#endif } else if (convert_pyobject_to_@name@(&ret->obmeta, obj, &ret->obval) < 0) { diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index 994066137..2d13d399e 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -14,7 +14,10 @@ class TestDateTime(TestCase): assert_(dt1 == np.dtype('datetime64[750%s]' % unit)) dt2 = np.dtype('m8[%s]' % unit) assert_(dt2 == np.dtype('timedelta64[%s]' % unit)) - + + # Generic units shouldn't add [] to the end + assert_equal(str(np.dtype("M8")), "datetime64") + # Check that the parser rejects bad datetime types assert_raises(TypeError, np.dtype, 'M8[badunit]') assert_raises(TypeError, np.dtype, 'm8[badunit]') @@ -80,8 +83,15 @@ class TestDateTime(TestCase): assert_equal(np.datetime64('1950-03-12', 's'), np.datetime64('1950-03-12', 'm')) - # Default construction means 0 - assert_equal(np.datetime64(), np.datetime64(0)) + # Default construction means NaT + assert_equal(np.datetime64(), np.datetime64('NaT')) + + # Default construction of NaT is in generic units + assert_equal(np.datetime64().dtype, np.dtype('M8')) + assert_equal(np.datetime64('NaT').dtype, np.dtype('M8')) + + # Construction from integers requires a specified unit + assert_raises(ValueError, np.datetime64, 17) # When constructing from a scalar or zero-dimensional array, # it either keeps the units or you can override them. @@ -123,6 +133,9 @@ class TestDateTime(TestCase): # Default construction means 0 assert_equal(np.timedelta64(), np.timedelta64(0)) + # Construction from an integer produces generic units + assert_equal(np.timedelta64(12).dtype, np.dtype('m8')) + # When constructing from a scalar or zero-dimensional array, # it either keeps the units or you can override them. a = np.timedelta64(2, 'h') @@ -858,96 +871,102 @@ class TestDateTime(TestCase): def test_string_parser_variants(self): # Allow space instead of 'T' between date and time - assert_equal(np.array(['1980-02-29T01:02:03'], np.dtype('M8')), - np.array(['1980-02-29 01:02:03'], np.dtype('M8'))) + assert_equal(np.array(['1980-02-29T01:02:03'], np.dtype('M8[s]')), + np.array(['1980-02-29 01:02:03'], np.dtype('M8[s]'))) # Allow negative years - assert_equal(np.array(['-1980-02-29T01:02:03'], np.dtype('M8')), - np.array(['-1980-02-29 01:02:03'], np.dtype('M8'))) + assert_equal(np.array(['-1980-02-29T01:02:03'], np.dtype('M8[s]')), + np.array(['-1980-02-29 01:02:03'], np.dtype('M8[s]'))) # UTC specifier - assert_equal(np.array(['-1980-02-29T01:02:03Z'], np.dtype('M8')), - np.array(['-1980-02-29 01:02:03Z'], np.dtype('M8'))) + assert_equal(np.array(['-1980-02-29T01:02:03Z'], np.dtype('M8[s]')), + np.array(['-1980-02-29 01:02:03Z'], np.dtype('M8[s]'))) # Time zone offset - assert_equal(np.array(['1980-02-29T02:02:03Z'], np.dtype('M8')), - np.array(['1980-02-29 00:32:03-0130'], np.dtype('M8'))) - assert_equal(np.array(['1980-02-28T22:32:03Z'], np.dtype('M8')), - np.array(['1980-02-29 00:02:03+01:30'], np.dtype('M8'))) - assert_equal(np.array(['1980-02-29T02:32:03.506Z'], np.dtype('M8')), - np.array(['1980-02-29 00:32:03.506-02'], np.dtype('M8'))) + assert_equal(np.array(['1980-02-29T02:02:03Z'], np.dtype('M8[s]')), + np.array(['1980-02-29 00:32:03-0130'], np.dtype('M8[s]'))) + assert_equal(np.array(['1980-02-28T22:32:03Z'], np.dtype('M8[s]')), + np.array(['1980-02-29 00:02:03+01:30'], np.dtype('M8[s]'))) + assert_equal(np.array(['1980-02-29T02:32:03.506Z'], np.dtype('M8[s]')), + np.array(['1980-02-29 00:32:03.506-02'], np.dtype('M8[s]'))) assert_equal(np.datetime64('1977-03-02T12:30-0230'), np.datetime64('1977-03-02T15:00Z')) def test_string_parser_error_check(self): # Arbitrary bad string - assert_raises(ValueError, np.array, ['badvalue'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['badvalue'], np.dtype('M8[us]')) # Character after year must be '-' - assert_raises(ValueError, np.array, ['1980X'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['1980X'], np.dtype('M8[us]')) # Cannot have trailing '-' - assert_raises(ValueError, np.array, ['1980-'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['1980-'], np.dtype('M8[us]')) # Month must be in range [1,12] - assert_raises(ValueError, np.array, ['1980-00'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-13'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['1980-00'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-13'], np.dtype('M8[us]')) # Month must have two digits - assert_raises(ValueError, np.array, ['1980-1'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-1-02'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['1980-1'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-1-02'], np.dtype('M8[us]')) # 'Mor' is not a valid month - assert_raises(ValueError, np.array, ['1980-Mor'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['1980-Mor'], np.dtype('M8[us]')) # Cannot have trailing '-' - assert_raises(ValueError, np.array, ['1980-01-'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['1980-01-'], np.dtype('M8[us]')) # Day must be in range [1,len(month)] - assert_raises(ValueError, np.array, ['1980-01-0'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-01-00'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-01-32'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1979-02-29'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-02-30'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-03-32'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-04-31'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-05-32'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-06-31'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-07-32'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-08-32'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-09-31'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-10-32'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-11-31'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-12-32'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['1980-01-0'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-01-00'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-01-32'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1979-02-29'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-02-30'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-03-32'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-04-31'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-05-32'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-06-31'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-07-32'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-08-32'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-09-31'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-10-32'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-11-31'], np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-12-32'], np.dtype('M8[us]')) # Cannot have trailing characters - assert_raises(ValueError, np.array, ['1980-02-03%'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-02-03 q'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['1980-02-03%'], + np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-02-03 q'], + np.dtype('M8[us]')) # Hours must be in range [0, 23] - assert_raises(ValueError, np.array, ['1980-02-03 25'], np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-02-03T25'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['1980-02-03 25'], + np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-02-03T25'], + np.dtype('M8[us]')) assert_raises(ValueError, np.array, ['1980-02-03 24:01'], - np.dtype('M8')) + np.dtype('M8[us]')) assert_raises(ValueError, np.array, ['1980-02-03T24:01'], - np.dtype('M8')) - assert_raises(ValueError, np.array, ['1980-02-03 -1'], np.dtype('M8')) + np.dtype('M8[us]')) + assert_raises(ValueError, np.array, ['1980-02-03 -1'], + np.dtype('M8[us]')) # No trailing ':' - assert_raises(ValueError, np.array, ['1980-02-03 01:'], np.dtype('M8')) + assert_raises(ValueError, np.array, ['1980-02-03 01:'], + np.dtype('M8[us]')) # Minutes must be in range [0, 59] assert_raises(ValueError, np.array, ['1980-02-03 01:-1'], - np.dtype('M8')) + np.dtype('M8[us]')) assert_raises(ValueError, np.array, ['1980-02-03 01:60'], - np.dtype('M8')) + np.dtype('M8[us]')) # No trailing ':' assert_raises(ValueError, np.array, ['1980-02-03 01:60:'], - np.dtype('M8')) + np.dtype('M8[us]')) # Seconds must be in range [0, 59] assert_raises(ValueError, np.array, ['1980-02-03 01:10:-1'], - np.dtype('M8')) + np.dtype('M8[us]')) assert_raises(ValueError, np.array, ['1980-02-03 01:01:60'], - np.dtype('M8')) + np.dtype('M8[us]')) # Timezone offset must within a reasonable range assert_raises(ValueError, np.array, ['1980-02-03 01:01:00+0661'], - np.dtype('M8')) + np.dtype('M8[us]')) assert_raises(ValueError, np.array, ['1980-02-03 01:01:00+2500'], - np.dtype('M8')) + np.dtype('M8[us]')) assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-0070'], - np.dtype('M8')) + np.dtype('M8[us]')) assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-3000'], - np.dtype('M8')) + np.dtype('M8[us]')) assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-25:00'], - np.dtype('M8')) + np.dtype('M8[us]')) def test_creation_overflow(self): |