����JFIFXX�����    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222����"��4�� ���,�PG"Z_�4�˷����kjز�Z�,F+��_z�,�© �����zh6�٨�ic�fu���#ډb���_�N�?��wQ���5-�~�I���8����TK<5o�Iv-�����k�_U_�����~b�M��d����Ӝ�U�Hh��?]��E�w��Q���k�{��_}qFW7HTՑ��Y��F�?_�'ϔ��_�Ջt��=||I ��6�έ"�����D���/[�k�9���Y�8ds|\���Ҿp6�Ҵ���]��.����6�z<�v��@]�i%��$j��~�g��J>��no����pM[me�i$[����s�o�ᘨ�˸ nɜG-�ĨU�ycP�3.DB�li�;��hj���x7Z^�N�h������N3u{�:j�x�힞��#M&��jL P@_���� P��&��o8������9�����@Sz6�t7#O�ߋ �s}Yf�T���lmr����Z)'N��k�۞p����w\�Tȯ?�8`�O��i{wﭹW�[�r�� ��Q4F�׊���3m&L�=��h3����z~��#�\�l :�F,j@�� ʱ�wQT����8�"kJO���6�֚l����}���R�>ډK���]��y����&����p�}b��;N�1�m�r$�|��7�>e�@B�TM*-iH��g�D�)� E�m�|�ؘbҗ�a��Ҿ����t4���o���G��*oCN�rP���Q��@z,|?W[0�����:�n,jWiE��W��$~/�hp\��?��{(�0���+�Y8rΟ�+����>S-S����VN;�}�s?.����� w�9��˟<���Mq4�Wv'��{)0�1mB��V����W[�����8�/<� �%���wT^�5���b��)iM� pg�N�&ݝ��VO~�q���u���9� ����!��J27����$O-���! �:�%H��� ـ����y�ΠM=t{!S�� oK8������t<����è:a������[�����ա�H���~��w��Qz`�po�^ ����Q��n� �,uu�C�$ ^���,������8�#��:�6��e�|~���!�3�3.�\0��q��o�4`.|� ����y�Q�`~;�d�ׯ,��O�Zw�������`73�v�܋�<���Ȏ�� ـ4k��5�K�a�u�=9Yd��$>x�A�&�� j0� ���vF��� Y�|�y��� ~�6�@c��1vOp�Ig����4��l�OD���L����� R���c���j�_�uX6��3?nk��Wy�f;^*B� ��@�~a�`��Eu������+���6�L��.ü>��}y���}_�O�6�͐�:�YrG�X��kG�����l^w���~㒶sy��Iu�!� W ��X��N�7BV��O��!X�2����wvG�R�f�T#�����t�/?���%8�^�W�aT��G�cL�M���I��(J����1~�8�?aT ���]����AS�E��(��*E}� 2��#I/�׍qz��^t�̔���b�Yz4x���t�){ OH��+(E��A&�N�������XT��o��"�XC��'���)}�J�z�p� ��~5�}�^����+�6����w��c��Q�|Lp�d�H��}�(�.|����k��c4^�"�����Z?ȕ ��a<�L�!039C� �Eu�C�F�Ew�ç ;�n?�*o���B�8�bʝ���'#Rqf���M}7����]����s2tcS{�\icTx;�\��7K���P���ʇ Z O-��~��c>"��?�������P��E��O�8��@�8��G��Q�g�a�Վ���󁶠�䧘��_%#r�>�1�z�a��eb��qcPѵ��n���#L��� =��׀t� L�7�`��V���A{�C:�g���e@�w1 Xp3�c3�ġ����p��M"'-�@n4���fG��B3�DJ�8[Jo�ߐ���gK)ƛ��$���� ���8�3�����+���� �����6�ʻ���� ���S�kI�*KZlT _`���?��K����QK�d����B`�s}�>���`��*�>��,*@J�d�oF*����弝��O}�k��s��]��y�ߘ��c1G�V���<=�7��7����6�q�PT��tXԀ�!9*4�4Tހ3XΛex�46���Y��D ����� �BdemDa����\�_l,��G�/���֌7���Y�](�xTt^%�GE�����4�}bT���ڹ�����;Y)���B�Q��u��>J/J �⮶.�XԄ��j�ݳ�+E��d ��r�5�_D�1 ��o�� �B�x�΢�#���<��W�����8���R6�@g�M�.��� dr�D��>(otU��@x=��~v���2� ӣ�d�oBd��3�eO�6�㣷�����ݜ6��6Y��Qz`��S��{���\P�~z m5{J/L��1������<�e�ͅPu�b�]�ϔ���'������f�b� Zpw��c`"��i���BD@:)ִ�:�]��hv�E�w���T�l��P���"Ju�}��وV J��G6��. J/�Qgl߭�e�����@�z�Zev2u�)]կ�����7x���s�M�-<ɯ�c��r�v�����@��$�ޮ}lk���a���'����>x��O\�ZFu>�����ck#��&:��`�$�ai�>2Δ����l���oF[h��lE�ܺ�Πk:)���`�� $[6�����9�����kOw�\|���8}������ބ:��񶐕��I�A1/�=�2[�,�!��.}gN#�u����b��� ~��݊��}34q����d�E��Lc��$��"�[q�U�硬g^��%B �z���r�pJ�ru%v\h1Y�ne`ǥ:g���pQM~�^�Xi� ��`S�:V29.�P���V�?B�k�� AEvw%�_�9C�Q����wKekPؠ�\�;Io d�{ ߞo�c1eP����\� `����E=���@K<�Y���eڼ�J���w����{av�F�'�M�@/J��+9p���|]�����Iw &`��8���&M�hg��[�{��Xj��%��Ӓ�$��(����ʹN���<>�I���RY���K2�NPlL�ɀ)��&e����B+ь����( � �JTx���_?EZ� }@ 6�U���뙢ط�z��dWI�n` D����噥�[��uV��"�G&Ú����2g�}&m��?ċ�"����Om#��������� ��{�ON��"S�X��Ne��ysQ���@Fn��Vg���dX�~nj�]J�<�K]:��FW��b�������62�=��5f����JKw��bf�X�55��~J �%^����:�-�QIE��P��v�nZum� z � ~ə ���� ���ة����;�f��\v���g�8�1��f24;�V���ǔ�)����9���1\��c��v�/'Ƞ�w�������$�4�R-��t���� e�6�/�ġ �̕Ecy�J���u�B���<�W�ַ~�w[B1L۲�-JS΂�{���΃������A��20�c#��@ 0!1@AP"#2Q`$3V�%45a6�FRUq��� ����^7ׅ,$n�������+��F�`��2X'��0vM��p�L=������5��8������u�p~���.�`r�����\���O��,ư�0oS ��_�M�����l���4�kv\JSd���x���SW�<��Ae�IX����������$I���w�:S���y���›R��9�Q[���,�5�;�@]�%���u�@ *ro�lbI �� ��+���%m:�͇ZV�����u�̉����θau<�fc�.����{�4Ա� �Q����*�Sm��8\ujqs]{kN���)qO�y�_*dJ�b�7���yQqI&9�ԌK!�M}�R�;������S�T���1���i[U�ɵz�]��U)V�S6���3$K{�ߊ<�(� E]Զ[ǼENg�����'�\?#)Dkf��J���o��v���'�%ƞ�&K�u�!��b�35LX�Ϸ��63$K�a�;�9>,R��W��3�3� d�JeTYE.Mϧ��-�o�j3+y��y^�c�������VO�9NV\nd�1 ��!͕_)a�v;����թ�M�lWR1��)El��P;��yوÏ�u 3�k�5Pr6<�⒲l�!˞*��u־�n�!�l:����UNW ��%��Chx8vL'��X�@��*��)���̮��ˍ��� ���D-M�+J�U�kvK����+�x8��cY������?�Ԡ��~3mo��|�u@[XeY�C�\Kp�x8�oC�C�&����N�~3-H���� ��MX�s�u<`���~"WL��$8ξ��3���a�)|:@�m�\���^�`�@ҷ)�5p+��6���p�%i)P M���ngc�����#0Aruz���RL+xSS?���ʮ}()#�t��mˇ!��0}}y����<�e� �-ή�Ԩ��X������ MF���ԙ~l L.3���}�V뽺�v�����멬��Nl�)�2����^�Iq��a��M��qG��T�����c3#������3U�Ǎ���}��לS�|qa��ڃ�+���-��2�f����/��bz��ڐ�� �ݼ[2�ç����k�X�2�* �Z�d���J�G����M*9W���s{��w���T��x��y,�in�O�v��]���n����P�$�JB@=4�OTI�n��e�22a\����q�d���%�$��(���:���: /*�K[PR�fr\nڙdN���F�n�$�4�[�� U�zƶ����� �mʋ���,�ao�u 3�z� �x��Kn����\[��VFmbE;�_U��&V�Gg�]L�۪&#n%�$ɯ�dG���D�TI=�%+AB�Ru#��b4�1�»x�cs�YzڙJG��f��Il��d�eF'T� iA��T���uC�$����Y��H?����[!G`}���ͪ� �纤Hv\������j�Ex�K���!���OiƸ�Yj�+u-<���'q����uN�*�r\��+�]���<�wOZ.fp�ێ��,-*)V?j-kÊ#�`�r��dV����(�ݽBk�����G�ƛk�QmUڗe��Z���f}|����8�8��a���i��3'J�����~G_�^���d�8w������ R�`(�~�.��u���l�s+g�bv���W���lGc}��u���afE~1�Ue������Z�0�8�=e�� f@/�jqEKQQ�J��oN��J���W5~M>$6�Lt�;$ʳ{���^��6�{����v6���ķܰg�V�cnn �~z�x�«�,2�u�?cE+Ș�H؎�%�Za�)���X>uW�Tz�Nyo����s���FQƤ��$��*�&�LLXL)�1�" L��eO��ɟ�9=���:t��Z���c��Ž���Y?�ӭV�wv�~,Y��r�ۗ�|�y��GaF�����C�����.�+� ���v1���fήJ�����]�S��T��B��n5sW}y�$��~z�'�c ��8 ��� ,! �p��VN�S��N�N�q��y8z˱�A��4��*��'������2n<�s���^ǧ˭P�Jޮɏ�U�G�L�J�*#��<�V��t7�8����TĜ>��i}K%,���)[��z�21z ?�N�i�n1?T�I�R#��m-�����������������1����lA�`��fT5+��ܐ�c�q՝��ʐ��,���3�f2U�եmab��#ŠdQ�y>\��)�SLY����w#��.���ʑ�f��� ,"+�w�~�N�'�c�O�3F�������N<���)j��&��,-� �љ���֊�_�zS���TǦ����w�>��?�������n��U仆�V���e�����0���$�C�d���rP �m�׈e�Xm�Vu� �L��.�bֹ��� �[Դaզ���*��\y�8�Է:�Ez\�0�Kq�C b��̘��cө���Q��=0Y��s�N��S.���3.���O�o:���#���v7�[#߫ ��5�܎�L���Er4���9n��COWlG�^��0k�%<���ZB���aB_���������'=��{i�v�l�$�uC���mƎҝ{�c㱼�y]���W�i ��ߧc��m�H� m�"�"�����;Y�ߝ�Z�Ǔ�����:S#��|}�y�,/k�Ld� TA�(�AI$+I3��;Y*���Z��}|��ӧO��d�v��..#:n��f>�>���ȶI�TX��� 8��y����"d�R�|�)0���=���n4��6ⲑ�+��r<�O�܂~zh�z����7ܓ�HH�Ga롏���nCo�>������a ���~]���R���̲c?�6(�q�;5%� |�uj�~z8R=X��I�V=�|{v�Gj\gc��q����z�؋%M�ߍ����1y��#��@f^���^�>N�����#x#۹��6�Y~�?�dfPO��{��P�4��V��u1E1J �*|���%���JN��`eWu�zk M6���q t[�� ��g�G���v��WIG��u_ft����5�j�"�Y�:T��ɐ���*�;� e5���4����q$C��2d�}���� _S�L#m�Yp��O�.�C�;��c����Hi#֩%+) �Ӎ��ƲV���SYź��g |���tj��3�8���r|���V��1#;.SQ�A[���S������#���`n�+���$��$I �P\[�@�s��(�ED�z���P��])8�G#��0B��[ى��X�II�q<��9�~[Z멜�Z�⊔IWU&A>�P~�#��dp<�?����7���c��'~���5 ��+$���lx@�M�dm��n<=e�dyX��?{�|Aef ,|n3�<~z�ƃ�uۧ�����P��Y,�ӥQ�*g�#먙R�\���;T��i,��[9Qi歉����c>]9�� ��"�c��P�� �Md?٥��If�ت�u��k��/����F��9�c*9��Ǎ:�ØF���z�n*�@|I�ށ9����N3{'��[�'ͬ�Ҳ4��#}��!�V� Fu��,�,mTIk���v C�7v���B�6k�T9��1�*l� '~��ƞF��lU��'�M ����][ΩũJ_�{�i�I�n��$���L�� j��O�dx�����kza۪��#�E��Cl����x˘�o�����V���ɞ�ljr��)�/,�߬h�L��#��^��L�ф�,íMƁe�̩�NB�L�����iL����q�}��(��q��6IçJ$�W�E$��:������=#����(�K�B����zђ <��K(�N�۫K�w��^O{!����)�H���>x�������lx�?>Պ�+�>�W���,Ly!_�D���Ō�l���Q�!�[ �S����J��1��Ɛ�Y}��b,+�Lo�x�ɓ)����=�y�oh�@�꥟/��I��ѭ=��P�y9��� �ۍYӘ�e+�p�Jnϱ?V\SO%�(�t� ���=?MR�[Ș�����d�/ ��n�l��B�7j� ��!�;ӥ�/�[-���A�>�dN�sLj ��,ɪv��=1c�.SQ�O3�U���ƀ�ܽ�E����������̻��9G�ϷD�7(�}��Ävӌ\�y�_0[w ���<΍>����a_��[0+�L��F.�޺��f�>oN�T����q;���y\��bՃ��y�jH�<|q-eɏ�_?_9+P���Hp$�����[ux�K w�Mw��N�ی'$Y2�=��q���KB��P��~������Yul:�[<����F1�2�O���5=d����]Y�sw:���Ϯ���E��j,_Q��X��z`H1,#II ��d�wr��P˂@�ZJV����y$�\y�{}��^~���[:N����ߌ�U�������O��d�����ؾe��${p>G��3c���Ė�lʌ�� ת��[��`ϱ�-W����dg�I��ig2��� ��}s ��ؤ(%#sS@���~���3�X�nRG�~\jc3�v��ӍL��M[JB�T��s3}��j�Nʖ��W����;7��ç?=X�F=-�=����q�ߚ���#���='�c��7���ڑW�I(O+=:uxq�������������e2�zi+�kuG�R��������0�&e�n���iT^J����~\jy���p'dtG��s����O��3����9* �b#Ɋ�� p������[Bws�T�>d4�ۧs���nv�n���U���_�~,�v����ƜJ1��s�� �QIz��)�(lv8M���U=�;����56��G���s#�K���MP�=��LvyGd��}�VwWBF�'�à �?MH�U�g2�� ����!�p�7Q��j��ڴ����=��j�u��� Jn�A s���uM������e��Ɔ�Ҕ�!)'��8Ϣ�ٔ��ޝ(��Vp���צ֖d=�IC�J�Ǡ{q������kԭ�߸���i��@K����u�|�p=..�*+����x�����z[Aqġ#s2a�Ɗ���RR�)*HRsi�~�a &f��M��P����-K�L@��Z��Xy�'x�{}��Zm+���:�)�) IJ�-i�u���� ���ܒH��'�L(7�y�GӜq���� j��� 6ߌg1�g�o���,kر���tY�?W,���p���e���f�OQS��!K�۟cҒA�|ս�j�>��=⬒��˧L[�� �߿2JaB~R��u�:��Q�] �0H~���]�7��Ƽ�I���(}��cq '�ήET���q�?f�ab���ӥvr� �)o��-Q��_'����ᴎo��K������;��V���o��%���~OK ����*��b�f:���-ťIR��`B�5!RB@���ï�� �u �̯e\�_U�_������� g�ES��3�������QT��a����x����U<~�c?�*�#]�MW,[8O�a�x��]�1bC|踤�P��lw5V%�)�{t�<��d��5���0i�XSU��m:��Z�┵�i�"��1�^B�-��P�hJ��&)O��*�D��c�W��vM��)����}���P��ܗ-q����\mmζZ-l@�}��a��E�6��F�@��&Sg@���ݚ�M����� ȹ 4����#p�\H����dYDo�H���"��\��..R�B�H�z_�/5˘����6��KhJR��P�mƶi�m���3�,#c�co��q�a)*Pt����R�m�k�7x�D�E�\Y�閣_X�<���~�)���c[[�BP����6�Yq���S��0����%_����;��Àv�~�| VS؇ ��'O0��F0��\���U�-�d@�����7�SJ*z��3n��y��P����O���������m�~�P�3|Y��ʉr#�C�<�G~�.,! ���bqx���h~0=��!ǫ�jy����l�O,�[B��~��|9��ٱ����Xly�#�i�B��g%�S��������tˋ���e���ې��\[d�t)��.+u�|1 ������#�~Oj����hS�%��i.�~X���I�H�m��0n���c�1uE�q��cF�RF�o���7� �O�ꮧ� ���ۛ{��ʛi5�rw?׌#Qn�TW��~?y$��m\�\o����%W� ?=>S�N@�� �Ʈ���R����N�)�r"C�:��:����� �����#��qb��Y�. �6[��2K����2u�Ǧ�HYR��Q�MV��� �G�$��Q+.>�����nNH��q�^��� ����q��mM��V��D�+�-�#*�U�̒ ���p욳��u:�������IB���m���PV@O���r[b= �� ��1U�E��_Nm�yKbN�O���U�}�the�`�|6֮P>�\2�P�V���I�D�i�P�O;�9�r�mAHG�W�S]��J*�_�G��+kP�2����Ka�Z���H�'K�x�W�MZ%�O�YD�Rc+o��?�q��Ghm��d�S�oh�\�D�|:W������UA�Qc yT�q������~^�H��/��#p�CZ���T�I�1�ӏT����4��"�ČZ�����}��`w�#�*,ʹ�� ��0�i��課�Om�*�da��^gJ݅{���l�e9uF#T�ֲ��̲�ٞC"�q���ߍ ոޑ�o#�XZTp����@ o�8��(jd��xw�]�,f���`~�|,s��^����f�1���t��|��m�򸄭/ctr��5s��7�9Q�4�H1꠲BB@l9@���C�����+�wp�xu�£Yc�9��?`@#�o�mH�s2��)�=��2�.�l����jg�9$�Y�S�%*L������R�Y������7Z���,*=�䷘$�������arm�o�ϰ���UW.|�r�uf����IGw�t����Zwo��~5 ��YյhO+=8fF�)�W�7�L9lM�̘·Y���֘YLf�큹�pRF���99.A �"wz��=E\Z���'a� 2��Ǚ�#;�'}�G���*��l��^"q��+2FQ� hj��kŦ��${���ޮ-�T�٭cf�|�3#~�RJ����t��$b�(R��(����r���dx� >U b�&9,>���%E\� Ά�e�$��'�q't��*�א���ެ�b��-|d���SB�O�O��$�R+�H�)�܎�K��1m`;�J�2�Y~9��O�g8=vqD`K[�F)k�[���1m޼c��n���]s�k�z$@��)!I �x՝"v��9=�ZA=`Ɠi �:�E��)`7��vI��}d�YI�_ �o�:ob���o ���3Q��&D&�2=�� �Ά��;>�h����y.*ⅥS������Ӭ�+q&����j|UƧ����}���J0��WW< ۋS�)jQR�j���Ư��rN)�Gű�4Ѷ(�S)Ǣ�8��i��W52���No˓� ۍ%�5brOn�L�;�n��\G����=�^U�dI���8$�&���h��'���+�(������cȁ߫k�l��S^���cƗjԌE�ꭔ��gF���Ȓ��@���}O���*;e�v�WV���YJ\�]X'5��ղ�k�F��b 6R�o՜m��i N�i����>J����?��lPm�U��}>_Z&�KK��q�r��I�D�Չ~�q�3fL�:S�e>���E���-G���{L�6p�e,8��������QI��h��a�Xa��U�A'���ʂ���s�+טIjP�-��y�8ۈZ?J$��W�P� ��R�s�]��|�l(�ԓ��sƊi��o(��S0��Y� 8�T97.�����WiL��c�~�dxc�E|�2!�X�K�Ƙਫ਼�$((�6�~|d9u+�qd�^3�89��Y�6L�.I�����?���iI�q���9�)O/뚅����O���X��X�V��ZF[�یgQ�L��K1���RҖr@v�#��X�l��F���Нy�S�8�7�kF!A��sM���^rkp�jP�DyS$N���q��nxҍ!U�f�!eh�i�2�m���`�Y�I�9r�6� �TF���C}/�y�^���Η���5d�'��9A-��J��>{�_l+�`��A���[�'��յ�ϛ#w:݅�%��X�}�&�PSt�Q�"�-��\縵�/����$Ɨh�Xb�*�y��BS����;W�ջ_mc�����vt?2}1�;qS�d�d~u:2k5�2�R�~�z+|HE!)�Ǟl��7`��0�<�,�2*���Hl-��x�^����'_TV�gZA�'j� ^�2Ϊ��N7t�����?w�� �x1��f��Iz�C-Ȗ��K�^q�;���-W�DvT�7��8�Z�������� hK�(P:��Q- �8�n�Z���܃e貾�<�1�YT<�,�����"�6{/ �?�͟��|1�:�#g��W�>$����d��J��d�B��=��jf[��%rE^��il:��B���x���Sּ�1հ��,�=��*�7 fcG��#q� �eh?��2�7�����,�!7x��6�n�LC�4x��},Geǝ�tC.��vS �F�43��zz\��;QYC,6����~;RYS/6���|2���5���v��T��i����������mlv��������&� �nRh^ejR�LG�f���? �ۉҬܦƩ��|��Ȱ����>3����!v��i�ʯ�>�v��オ�X3e���_1z�Kȗ\<������!�8���V��]��?b�k41�Re��T�q��mz��TiOʦ�Z��Xq���L������q"+���2ۨ��8}�&N7XU7Ap�d�X��~�׿��&4e�o�F��� �H����O���č�c�� 懴�6���͉��+)��v;j��ݷ�� �UV�� i��� j���Y9GdÒJ1��詞�����V?h��l����l�cGs�ځ�������y�Ac�����\V3�? �� ܙg�>qH�S,�E�W�[�㺨�uch�⍸�O�}���a��>�q�6�n6����N6�q������N ! 1AQaq�0@����"2BRb�#Pr���3C`��Scst���$4D���%Td�� ?���N����a��3��m���C���w��������xA�m�q�m���m������$����4n淿t'��C"w��zU=D�\R+w�p+Y�T�&�պ@��ƃ��3ޯ?�Aﶂ��aŘ���@-�����Q�=���9D��ռ�ѻ@��M�V��P��܅�G5�f�Y<�u=,EC)�<�Fy'�"�&�չ�X~f��l�KԆV��?�� �W�N����=(� �;���{�r����ٌ�Y���h{�١������jW����P���Tc�����X�K�r��}���w�R��%��?���E��m�� �Y�q|����\lEE4���r���}�lsI�Y������f�$�=�d�yO����p�����yBj8jU�o�/�S��?�U��*������ˍ�0������u�q�m [�?f����a�� )Q�>����6#������� ?����0UQ����,IX���(6ڵ[�DI�MNލ�c&���υ�j\��X�R|,4��� j������T�hA�e��^���d���b<����n�� �즇�=!���3�^�`j�h�ȓr��jẕ�c�,ٞX����-����a�ﶔ���#�$��]w�O��Ӫ�1y%��L�Y<�wg#�ǝ�̗`�x�xa�t�w��»1���o7o5��>�m뭛C���Uƃߜ}�C���y1Xνm�F8�jI���]����H���ۺиE@I�i;r�8ӭ����V�F�Շ| ��&?�3|x�B�MuS�Ge�=Ӕ�#BE5G�����Y!z��_e��q�р/W>|-�Ci߇�t�1ޯќd�R3�u��g�=0 5��[?�#͏��q�cf���H��{ ?u�=?�?ǯ���}Z��z���hmΔ�BFTW�����<�q�(v� ��!��z���iW]*�J�V�z��gX֧A�q�&��/w���u�gYӘa���; �i=����g:��?2�dž6�ى�k�4�>�Pxs����}������G�9��3 ���)gG�R<>r h�$��'nc�h�P��Bj��J�ҧH� -��N1���N��?��~��}-q!=��_2hc�M��l�vY%UE�@|�v����M2�.Y[|y�"Eï��K�ZF,�ɯ?,q�?v�M 80jx�"�;�9vk�����+ ֧�� �ȺU��?�%�vcV��mA�6��Qg^M����A}�3�nl� QRN�l8�kkn�'�����(��M�7m9و�q���%ޟ���*h$Zk"��$�9��: �?U8�Sl��,,|ɒ��xH(ѷ����Gn�/Q�4�P��G�%��Ա8�N��!� �&�7�;���eKM7�4��9R/%����l�c>�x;������>��C�:�����t��h?aKX�bhe�ᜋ^�$�Iհ �hr7%F$�E��Fd���t��5���+�(M6�t����Ü�UU|zW�=a�Ts�Tg������dqP�Q����b'�m���1{|Y����X�N��b �P~��F^F:����k6�"�j!�� �I�r�`��1&�-$�Bevk:y���#yw��I0��x��=D�4��tU���P�ZH��ڠ底taP��6����b>�xa����Q�#� WeF��ŮNj�p�J* mQ�N����*I�-*�ȩ�F�g�3 �5��V�ʊ�ɮ�a��5F���O@{���NX��?����H�]3��1�Ri_u��������ѕ�� ����0��� F��~��:60�p�͈�S��qX#a�5>���`�o&+�<2�D����: �������ڝ�$�nP���*)�N�|y�Ej�F�5ټ�e���ihy�Z �>���k�bH�a�v��h�-#���!�Po=@k̆IEN��@��}Ll?j�O������߭�ʞ���Q|A07x���wt!xf���I2?Z��<ץ�T���cU�j��]��陎Ltl �}5�ϓ��$�,��O�mˊ�;�@O��jE��j(�ا,��LX���LO���Ц�90�O �.����a��nA���7������j4 ��W��_ٓ���zW�jcB������y՗+EM�)d���N�g6�y1_x��p�$Lv:��9�"z��p���ʙ$��^��JԼ*�ϭ����o���=x�Lj�6�J��u82�A�H�3$�ٕ@�=Vv�]�'�qEz�;I˼��)��=��ɯ���x �/�W(V���p�����$ �m�������u�����񶤑Oqˎ�T����r��㠚x�sr�GC��byp�G��1ߠ�w e�8�$⿄����/�M{*}��W�]˷.�CK\�ުx���/$�WPw���r� |i���&�}�{�X� �>��$-��l���?-z���g����lΆ���(F���h�vS*���b���߲ڡn,|)mrH[���a�3�ר�[1��3o_�U�3�TC�$��(�=�)0�kgP���� ��u�^=��4 �WYCҸ:��vQ�ר�X�à��tk�m,�t*��^�,�}D*� �"(�I��9R����>`�`��[~Q]�#af��i6l��8���6�:,s�s�N6�j"�A4���IuQ��6E,�GnH��zS�HO�uk�5$�I�4��ؤ�Q9�@��C����wp�BGv[]�u�Ov���0I4���\��y�����Q�Ѹ��~>Z��8�T��a��q�ޣ;z��a���/��S��I:�ܫ_�|������>=Z����8:�S��U�I�J��"IY���8%b8���H��:�QO�6�;7�I�S��J��ҌAά3��>c���E+&jf$eC+�z�;��V����� �r���ʺ������my�e���aQ�f&��6�ND��.:��NT�vm�<- u���ǝ\MvZY�N�NT��-A�>jr!S��n�O 1�3�Ns�%�3D@���`������ܟ 1�^c<���� �a�ɽ�̲�Xë#�w�|y�cW�=�9I*H8�p�^(4���՗�k��arOcW�tO�\�ƍR��8����'�K���I�Q�����?5�>[�}��yU�ײ -h��=��% q�ThG�2�)���"ו3]�!kB��*p�FDl�A���,�eEi�H�f�Ps�����5�H:�Փ~�H�0Dت�D�I����h�F3�������c��2���E��9�H��5�zԑ�ʚ�i�X�=:m�xg�hd(�v����׊�9iS��O��d@0ڽ���:�p�5�h-��t�&���X�q�ӕ,��ie�|���7A�2���O%P��E��htj��Y1��w�Ѓ!����  ���� ࢽ��My�7�\�a�@�ţ�J �4�Ȼ�F�@o�̒?4�wx��)��]�P��~�����u�����5�����7X ��9��^ܩ�U;Iꭆ 5 �������eK2�7(�{|��Y׎ �V��\"���Z�1� Z�����}��(�Ǝ"�1S���_�vE30>���p;� ΝD��%x�W�?W?v����o�^V�i�d��r[��/&>�~`�9Wh��y�;���R��� ;;ɮT��?����r$�g1�K����A��C��c��K��l:�'��3 c�ﳯ*"t8�~l��)���m��+U,z��`(�>yJ�?����h>��]��v��ЍG*�{`��;y]��I�T� ;c��NU�fo¾h���/$���|NS���1�S�"�H��V���T���4��uhǜ�]�v;���5�͠x��'C\�SBpl���h}�N����� A�Bx���%��ޭ�l��/����T��w�ʽ]D�=����K���ž�r㻠l4�S�O?=�k �M:� ��c�C�a�#ha���)�ѐxc�s���gP�iG��{+���x���Q���I= �� z��ԫ+ �8"�k�ñ�j=|����c ��y��CF��/��*9ж�h{ �?4�o� ��k�m�Q�N�x��;�Y��4膚�a�w?�6�>e]�����Q�r�:����g�,i"�����ԩA�*M�<�G��b�if��l^M��5� �Ҩ�{����6J��ZJ�����P�*�����Y���ݛu�_4�9�I8�7���������,^ToR���m4�H��?�N�S�ѕw��/S��甍�@�9H�S�T��t�ƻ���ʒU��*{Xs�@����f�����֒Li�K{H�w^���������Ϥm�tq���s� ���ք��f:��o~s��g�r��ט� �S�ѱC�e]�x���a��) ���(b-$(�j>�7q�B?ӕ�F��hV25r[7 Y� }L�R��}����*sg+��x�r�2�U=�*'WS��ZDW]�WǞ�<��叓���{�$�9Ou4��y�90-�1�'*D`�c�^o?(�9��u���ݐ��'PI&� f�Jݮ�������:wS����jfP1F:X �H�9dԯ���˝[�_54 �}*;@�ܨ�� ð�yn�T���?�ןd�#���4rG�ͨ��H�1�|-#���Mr�S3��G�3�����)�.᧏3v�z֑��r����$G"�`j �1t��x0<Ɔ�Wh6�y�6��,œ�Ga��gA����y��b��)��h�D��ß�_�m��ü �gG;��e�v��ݝ�nQ� ��C����-�*��o���y�a��M��I�>�<���]obD��"�:���G�A��-\%LT�8���c�)��+y76���o�Q�#*{�(F�⽕�y����=���rW�\p���۩�c���A���^e6��K������ʐ�cVf5$�'->���ՉN"���F�"�UQ@�f��Gb~��#�&�M=��8�ט�JNu9��D��[̤�s�o�~������ G��9T�tW^g5y$b��Y'��س�Ǵ�=��U-2 #�MC�t(�i� �lj�@Q 5�̣i�*�O����s�x�K�f��}\��M{E�V�{�υ��Ƈ�����);�H����I��fe�Lȣr�2��>��W�I�Ȃ6������i��k�� �5�YOxȺ����>��Y�f5'��|��H+��98pj�n�.O�y�������jY��~��i�w'������l�;�s�2��Y��:'lg�ꥴ)o#'Sa�a�K��Z� �m��}�`169�n���"���x��I ��*+� }F<��cГ���F�P�������ֹ*�PqX�x۩��,� ��N�� �4<-����%����:��7����W���u�`����� $�?�I��&����o��o��`v�>��P��"��l���4��5'�Z�gE���8���?��[�X�7(��.Q�-��*���ތL@̲����v��.5���[��=�t\+�CNܛ��,g�SQnH����}*F�G16���&:�t��4ُ"A��̣��$�b �|����#rs��a�����T�� ]�<�j��BS�('$�ɻ� �wP;�/�n��?�ݜ��x�F��yUn�~mL*-�������Xf�wd^�a�}��f�,=t�׵i�.2/wpN�Ep8�OР���•��R�FJ� 55TZ��T �ɭ�<��]��/�0�r�@�f��V��V����Nz�G��^���7hZi����k��3�,kN�e|�vg�1{9]_i��X5y7� 8e]�U����'�-2,���e"����]ot�I��Y_��n�(JҼ��1�O ]bXc���Nu�No��pS���Q_���_�?i�~�x h5d'�(qw52] ��'ޤ�q��o1�R!���`ywy�A4u���h<קy���\[~�4�\ X�Wt/� 6�����n�F�a8��f���z �3$�t(���q��q�x��^�XWeN'p<-v�!�{�(>ӽDP7��ո0�y)�e$ٕv�Ih'Q�EA�m*�H��RI��=:��� ���4牢) �%_iN�ݧ�l]� �Nt���G��H�L��� ɱ�g<���1V�,�J~�ٹ�"K��Q�� 9�HS�9�?@��k����r�;we݁�]I�!{ �@�G�[�"��`���J:�n]�{�cA�E����V��ʆ���#��U9�6����j�#Y�m\��q�e4h�B�7��C�������d<�?J����1g:ٳ���=Y���D�p�ц� ׈ǔ��1�]26؜oS�'��9�V�FVu�P�h�9�xc�oq�X��p�o�5��Ա5$�9W�V(�[Ak�aY錎qf;�'�[�|���b�6�Ck��)��#a#a˙��8���=äh�4��2��C��4tm^ �n'c���]GQ$[Wҿ��i���vN�{Fu ��1�gx��1┷���N�m��{j-,��x�� Ūm�ЧS�[�s���Gna���䑴�� x�p 8<������97�Q���ϴ�v�aϚG��Rt�Һ׈�f^\r��WH�JU�7Z���y)�vg=����n��4�_)y��D'y�6�]�c�5̪�\� �PF�k����&�c;��cq�$~T�7j ���nç]�<�g ":�to�t}�159�<�/�8������m�b�K#g'I'.W�����6��I/��>v��\�MN��g���m�A�yQL�4u�Lj�j9��#44�t��l^�}L����n��R��!��t��±]��r��h6ٍ>�yҏ�N��fU�� ���� Fm@�8}�/u��jb9������he:A�y�ծw��GpΧh�5����l}�3p468��)U��d��c����;Us/�֔�YX�1�O2��uq�s��`hwg�r~�{ R��mhN��؎*q 42�*th��>�#���E����#��Hv�O����q�}�����6�e��\�,Wk�#���X��b>��p}�դ��3���T5��†��6��[��@�P�y*n��|'f�֧>�lư΂�̺����SU�'*�q�p�_S�����M�� '��c�6�����m�� ySʨ;M��r���Ƌ�m�Kxo,���Gm�P��A�G�:��i��w�9�}M(�^�V��$ǒ�ѽ�9���|���� �a����J�SQ�a���r�B;����}���ٻ֢�2�%U���c�#�g���N�a�ݕ�'�v�[�OY'��3L�3�;,p�]@�S��{ls��X�'���c�jw�k'a�.��}�}&�� �dP�*�bK=ɍ!����;3n�gΊU�ߴmt�'*{,=SzfD� A��ko~�G�aoq�_mi}#�m�������P�Xhύ����mxǍ�΂���巿zf��Q���c���|kc�����?���W��Y�$���_Lv����l߶��c���`?����l�j�ݲˏ!V��6����U�Ђ(A���4y)H���p�Z_�x��>���e��R��$�/�`^'3qˏ�-&Q�=?��CFVR �D�fV�9��{�8g�������n�h�(P"��6�[�D���< E�����~0<@�`�G�6����Hг�cc�� �c�K.5��D��d�B���`?�XQ��2��ٿyqo&+�1^� DW�0�ꊩ���G�#��Q�nL3��c���������/��x ��1�1[y�x�პCW��C�c�UĨ80�m�e�4.{�m��u���I=��f�����0QRls9���f���������9���~f�����Ǩ��a�"@�8���ȁ�Q����#c�ic������G��$���G���r/$W�(��W���V�"��m�7�[m�A�m����bo��D� j����۳� l���^�k�h׽����� ��#� iXn�v��eT�k�a�^Y�4�BN��ĕ��0 !01@Q"2AaPq3BR������?���@4�Q�����T3,���㺠�W�[=JK�Ϟ���2�r^7��vc�:�9 �E�ߴ�w�S#d���Ix��u��:��Hp��9E!�� V 2;73|F��9Y���*ʬ�F��D����u&���y؟��^EA��A��(ɩ���^��GV:ݜDy�`��Jr29ܾ�㝉��[���E;Fzx��YG��U�e�Y�C���� ����v-tx����I�sם�Ę�q��Eb�+P\ :>�i�C'�;�����k|z�رn�y]�#ǿb��Q��������w�����(�r|ӹs��[�D��2v-%��@;�8<a���[\o[ϧw��I!��*0�krs)�[�J9^��ʜ��p1)� "��/_>��o��<1����A�E�y^�C��`�x1'ܣn�p��s`l���fQ��):�l����b>�Me�jH^?�kl3(�z:���1ŠK&?Q�~�{�ٺ�h�y���/�[��V�|6��}�KbX����mn[-��7�5q�94�������dm���c^���h� X��5��<�eޘ>G���-�}�دB�ޟ� ��|�rt�M��V+�]�c?�-#ڛ��^ǂ}���Lkr���O��u�>�-D�ry� D?:ޞ�U��ǜ�7�V��?瓮�"�#���r��չģVR;�n���/_� ؉v�ݶe5d�b9��/O��009�G���5n�W����JpA�*�r9�>�1��.[t���s�F���nQ� V 77R�]�ɫ8����_0<՜�IF�u(v��4��F�k�3��E)��N:��yڮe��P�`�1}�$WS��J�SQ�N�j�ٺ��޵�#l���ј(�5=��5�lǏmoW�v-�1����v,W�mn��߀$x�<����v�j(����c]��@#��1������Ǔ���o'��u+����;G�#�޸��v-lη��/(`i⣍Pm^���ԯ̾9Z��F��������n��1��� ��]�[��)�'������:�֪�W��FC����� �B9،!?���]��V��A�Վ�M��b�w��G F>_DȬ0¤�#�QR�[V��kz���m�w�"��9ZG�7'[��=�Q����j8R?�zf�\a�=��O�U����*oB�A�|G���2�54 �p��.w7� �� ��&������ξxGHp� B%��$g�����t�Џ򤵍z���HN�u�Я�-�'4��0��;_��3 !01"@AQa2Pq#3BR������?��ʩca��en��^��8���<�u#��m*08r��y�N"�<�Ѳ0��@\�p��� �����Kv�D��J8�Fҽ� �f�Y��-m�ybX�NP����}�!*8t(�OqѢ��Q�wW�K��ZD��Δ^e��!� ��B�K��p~�����e*l}z#9ң�k���q#�Ft�o��S�R����-�w�!�S���Ӥß|M�l޶V��!eˈ�8Y���c�ЮM2��tk���� ������J�fS����Ö*i/2�����n]�k�\���|4yX�8��U�P.���Ы[���l��@"�t�<������5�lF���vU�����W��W��;�b�cД^6[#7@vU�xgZv��F�6��Q,K�v��� �+Ъ��n��Ǣ��Ft���8��0��c�@�!�Zq s�v�t�;#](B��-�nῃ~���3g������5�J�%���O������n�kB�ĺ�.r��+���#�N$?�q�/�s�6��p��a����a��J/��M�8��6�ܰ"�*������ɗud"\w���aT(����[��F��U՛����RT�b���n�*��6���O��SJ�.�ij<�v�MT��R\c��5l�sZB>F��<7�;EA��{��E���Ö��1U/�#��d1�a�n.1ě����0�ʾR�h��|�R��Ao�3�m3 ��%�� ���28Q� ��y��φ���H�To�7�lW>����#i`�q���c����a��� �m,B�-j����݋�'mR1Ήt�>��V��p���s�0IbI�C.���1R�ea�����]H�6����������4B>��o��](��$B���m�����a�!=��?�B� K�Ǿ+�Ծ"�n���K��*��+��[T#�{E�J�S����Q�����s�5�:�U�\wĐ�f�3����܆&�)����I���Ԇw��E T�lrTf6Q|R�h:��[K�� �z��c֧�G�C��%\��_�a�84��HcO�bi��ؖV��7H �)*ģK~Xhչ0��4?�0��� �E<���}3���#���u�?�� ��|g�S�6ꊤ�|�I#Hڛ� �ա��w�X��9��7���Ŀ%�SL��y6č��|�F�a 8���b��$�sק�h���b9RAu7�˨p�Č�_\*w��묦��F ����4D~�f����|(�"m���NK��i�S�>�$d7SlA��/�²����SL��|6N�}���S�˯���g��]6��; �#�.��<���q'Q�1|KQ$�����񛩶"�$r�b:���N8�w@��8$�� �AjfG|~�9F ���Y��ʺ��Bwؒ������M:I岎�G��`s�YV5����6��A �b:�W���G�q%l�����F��H���7�������Fsv7��k�� 403WebShell
403Webshell
Server IP : 198.54.115.249  /  Your IP : 216.73.216.150
Web Server : LiteSpeed
System : Linux server66.web-hosting.com 4.18.0-553.44.1.lve.el8.x86_64 #1 SMP Thu Mar 13 14:29:12 UTC 2025 x86_64
User : digigcnj ( 11081)
PHP Version : 8.0.30
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/cloudlinux/venv/lib64/python3.11/site-packages/numpy/core/tests/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/cloudlinux/venv/lib64/python3.11/site-packages/numpy/core/tests/test_datetime.py
import numpy
import numpy as np
import datetime
import pytest
from numpy.testing import (
    IS_WASM,
    assert_, assert_equal, assert_raises, assert_warns, suppress_warnings,
    assert_raises_regex, assert_array_equal,
    )
from numpy.compat import pickle

# Use pytz to test out various time zones if available
try:
    from pytz import timezone as tz
    _has_pytz = True
except ImportError:
    _has_pytz = False

try:
    RecursionError
except NameError:
    RecursionError = RuntimeError  # python < 3.5


class TestDateTime:
    def test_datetime_dtype_creation(self):
        for unit in ['Y', 'M', 'W', 'D',
                     'h', 'm', 's', 'ms', 'us',
                     'μs',  # alias for us
                     'ns', 'ps', 'fs', 'as']:
            dt1 = np.dtype('M8[750%s]' % unit)
            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")

        # Should be possible to specify the endianness
        assert_equal(np.dtype("=M8"), np.dtype("M8"))
        assert_equal(np.dtype("=M8[s]"), np.dtype("M8[s]"))
        assert_(np.dtype(">M8") == np.dtype("M8") or
                np.dtype("<M8") == np.dtype("M8"))
        assert_(np.dtype(">M8[D]") == np.dtype("M8[D]") or
                np.dtype("<M8[D]") == np.dtype("M8[D]"))
        assert_(np.dtype(">M8") != np.dtype("<M8"))

        assert_equal(np.dtype("=m8"), np.dtype("m8"))
        assert_equal(np.dtype("=m8[s]"), np.dtype("m8[s]"))
        assert_(np.dtype(">m8") == np.dtype("m8") or
                np.dtype("<m8") == np.dtype("m8"))
        assert_(np.dtype(">m8[D]") == np.dtype("m8[D]") or
                np.dtype("<m8[D]") == np.dtype("m8[D]"))
        assert_(np.dtype(">m8") != np.dtype("<m8"))

        # Check that the parser rejects bad datetime types
        assert_raises(TypeError, np.dtype, 'M8[badunit]')
        assert_raises(TypeError, np.dtype, 'm8[badunit]')
        assert_raises(TypeError, np.dtype, 'M8[YY]')
        assert_raises(TypeError, np.dtype, 'm8[YY]')
        assert_raises(TypeError, np.dtype, 'm4')
        assert_raises(TypeError, np.dtype, 'M7')
        assert_raises(TypeError, np.dtype, 'm7')
        assert_raises(TypeError, np.dtype, 'M16')
        assert_raises(TypeError, np.dtype, 'm16')
        assert_raises(TypeError, np.dtype, 'M8[3000000000ps]')

    def test_datetime_casting_rules(self):
        # Cannot cast safely/same_kind between timedelta and datetime
        assert_(not np.can_cast('m8', 'M8', casting='same_kind'))
        assert_(not np.can_cast('M8', 'm8', casting='same_kind'))
        assert_(not np.can_cast('m8', 'M8', casting='safe'))
        assert_(not np.can_cast('M8', 'm8', casting='safe'))

        # Can cast safely/same_kind from integer to timedelta
        assert_(np.can_cast('i8', 'm8', casting='same_kind'))
        assert_(np.can_cast('i8', 'm8', casting='safe'))
        assert_(np.can_cast('i4', 'm8', casting='same_kind'))
        assert_(np.can_cast('i4', 'm8', casting='safe'))
        assert_(np.can_cast('u4', 'm8', casting='same_kind'))
        assert_(np.can_cast('u4', 'm8', casting='safe'))

        # Cannot cast safely from unsigned integer of the same size, which
        # could overflow
        assert_(np.can_cast('u8', 'm8', casting='same_kind'))
        assert_(not np.can_cast('u8', 'm8', casting='safe'))

        # Cannot cast safely/same_kind from float to timedelta
        assert_(not np.can_cast('f4', 'm8', casting='same_kind'))
        assert_(not np.can_cast('f4', 'm8', casting='safe'))

        # Cannot cast safely/same_kind from integer to datetime
        assert_(not np.can_cast('i8', 'M8', casting='same_kind'))
        assert_(not np.can_cast('i8', 'M8', casting='safe'))

        # Cannot cast safely/same_kind from bool to datetime
        assert_(not np.can_cast('b1', 'M8', casting='same_kind'))
        assert_(not np.can_cast('b1', 'M8', casting='safe'))
        # Can cast safely/same_kind from bool to timedelta
        assert_(np.can_cast('b1', 'm8', casting='same_kind'))
        assert_(np.can_cast('b1', 'm8', casting='safe'))

        # Can cast datetime safely from months/years to days
        assert_(np.can_cast('M8[M]', 'M8[D]', casting='safe'))
        assert_(np.can_cast('M8[Y]', 'M8[D]', casting='safe'))
        # Cannot cast timedelta safely from months/years to days
        assert_(not np.can_cast('m8[M]', 'm8[D]', casting='safe'))
        assert_(not np.can_cast('m8[Y]', 'm8[D]', casting='safe'))
        # Can cast datetime same_kind from months/years to days
        assert_(np.can_cast('M8[M]', 'M8[D]', casting='same_kind'))
        assert_(np.can_cast('M8[Y]', 'M8[D]', casting='same_kind'))
        # Can't cast timedelta same_kind from months/years to days
        assert_(not np.can_cast('m8[M]', 'm8[D]', casting='same_kind'))
        assert_(not np.can_cast('m8[Y]', 'm8[D]', casting='same_kind'))
        # Can cast datetime same_kind across the date/time boundary
        assert_(np.can_cast('M8[D]', 'M8[h]', casting='same_kind'))
        # Can cast timedelta same_kind across the date/time boundary
        assert_(np.can_cast('m8[D]', 'm8[h]', casting='same_kind'))
        assert_(np.can_cast('m8[h]', 'm8[D]', casting='same_kind'))

        # Cannot cast safely if the integer multiplier doesn't divide
        assert_(not np.can_cast('M8[7h]', 'M8[3h]', casting='safe'))
        assert_(not np.can_cast('M8[3h]', 'M8[6h]', casting='safe'))
        # But can cast same_kind
        assert_(np.can_cast('M8[7h]', 'M8[3h]', casting='same_kind'))
        # Can cast safely if the integer multiplier does divide
        assert_(np.can_cast('M8[6h]', 'M8[3h]', casting='safe'))

        # We can always cast types with generic units (corresponding to NaT) to
        # more specific types
        assert_(np.can_cast('m8', 'm8[h]', casting='same_kind'))
        assert_(np.can_cast('m8', 'm8[h]', casting='safe'))
        assert_(np.can_cast('M8', 'M8[h]', casting='same_kind'))
        assert_(np.can_cast('M8', 'M8[h]', casting='safe'))
        # but not the other way around
        assert_(not np.can_cast('m8[h]', 'm8', casting='same_kind'))
        assert_(not np.can_cast('m8[h]', 'm8', casting='safe'))
        assert_(not np.can_cast('M8[h]', 'M8', casting='same_kind'))
        assert_(not np.can_cast('M8[h]', 'M8', casting='safe'))

    def test_datetime_prefix_conversions(self):
        # regression tests related to gh-19631;
        # test metric prefixes from seconds down to
        # attoseconds for bidirectional conversions
        smaller_units = ['M8[7000ms]',
                         'M8[2000us]',
                         'M8[1000ns]',
                         'M8[5000ns]',
                         'M8[2000ps]',
                         'M8[9000fs]',
                         'M8[1000as]',
                         'M8[2000000ps]',
                         'M8[1000000as]',
                         'M8[2000000000ps]',
                         'M8[1000000000as]']
        larger_units = ['M8[7s]',
                        'M8[2ms]',
                        'M8[us]',
                        'M8[5us]',
                        'M8[2ns]',
                        'M8[9ps]',
                        'M8[1fs]',
                        'M8[2us]',
                        'M8[1ps]',
                        'M8[2ms]',
                        'M8[1ns]']
        for larger_unit, smaller_unit in zip(larger_units, smaller_units):
            assert np.can_cast(larger_unit, smaller_unit, casting='safe')
            assert np.can_cast(smaller_unit, larger_unit, casting='safe')

    @pytest.mark.parametrize("unit", [
        "s", "ms", "us", "ns", "ps", "fs", "as"])
    def test_prohibit_negative_datetime(self, unit):
        with assert_raises(TypeError):
            np.array([1], dtype=f"M8[-1{unit}]")

    def test_compare_generic_nat(self):
        # regression tests for gh-6452
        assert_(np.datetime64('NaT') !=
                np.datetime64('2000') + np.timedelta64('NaT'))
        assert_(np.datetime64('NaT') != np.datetime64('NaT', 'us'))
        assert_(np.datetime64('NaT', 'us') != np.datetime64('NaT'))

    @pytest.mark.parametrize("size", [
        3, 21, 217, 1000])
    def test_datetime_nat_argsort_stability(self, size):
        # NaT < NaT should be False internally for
        # sort stability
        expected = np.arange(size)
        arr = np.tile(np.datetime64('NaT'), size)
        assert_equal(np.argsort(arr, kind='mergesort'), expected)

    @pytest.mark.parametrize("size", [
        3, 21, 217, 1000])
    def test_timedelta_nat_argsort_stability(self, size):
        # NaT < NaT should be False internally for
        # sort stability
        expected = np.arange(size)
        arr = np.tile(np.timedelta64('NaT'), size)
        assert_equal(np.argsort(arr, kind='mergesort'), expected)

    @pytest.mark.parametrize("arr, expected", [
        # the example provided in gh-12629
        (['NaT', 1, 2, 3],
         [1, 2, 3, 'NaT']),
        # multiple NaTs
        (['NaT', 9, 'NaT', -707],
         [-707, 9, 'NaT', 'NaT']),
        # this sort explores another code path for NaT
        ([1, -2, 3, 'NaT'],
         [-2, 1, 3, 'NaT']),
        # 2-D array
        ([[51, -220, 'NaT'],
          [-17, 'NaT', -90]],
         [[-220, 51, 'NaT'],
          [-90, -17, 'NaT']]),
        ])
    @pytest.mark.parametrize("dtype", [
        'M8[ns]', 'M8[us]',
        'm8[ns]', 'm8[us]'])
    def test_datetime_timedelta_sort_nat(self, arr, expected, dtype):
        # fix for gh-12629 and gh-15063; NaT sorting to end of array
        arr = np.array(arr, dtype=dtype)
        expected = np.array(expected, dtype=dtype)
        arr.sort()
        assert_equal(arr, expected)

    def test_datetime_scalar_construction(self):
        # Construct with different units
        assert_equal(np.datetime64('1950-03-12', 'D'),
                     np.datetime64('1950-03-12'))
        assert_equal(np.datetime64('1950-03-12T13', 's'),
                     np.datetime64('1950-03-12T13', 'm'))

        # Default construction means NaT
        assert_equal(np.datetime64(), np.datetime64('NaT'))

        # Some basic strings and repr
        assert_equal(str(np.datetime64('NaT')), 'NaT')
        assert_equal(repr(np.datetime64('NaT')),
                     "numpy.datetime64('NaT')")
        assert_equal(str(np.datetime64('2011-02')), '2011-02')
        assert_equal(repr(np.datetime64('2011-02')),
                     "numpy.datetime64('2011-02')")

        # None gets constructed as NaT
        assert_equal(np.datetime64(None), 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.
        a = np.datetime64('2000-03-18T16', 'h')
        b = np.array('2000-03-18T16', dtype='M8[h]')

        assert_equal(a.dtype, np.dtype('M8[h]'))
        assert_equal(b.dtype, np.dtype('M8[h]'))

        assert_equal(np.datetime64(a), a)
        assert_equal(np.datetime64(a).dtype, np.dtype('M8[h]'))

        assert_equal(np.datetime64(b), a)
        assert_equal(np.datetime64(b).dtype, np.dtype('M8[h]'))

        assert_equal(np.datetime64(a, 's'), a)
        assert_equal(np.datetime64(a, 's').dtype, np.dtype('M8[s]'))

        assert_equal(np.datetime64(b, 's'), a)
        assert_equal(np.datetime64(b, 's').dtype, np.dtype('M8[s]'))

        # Construction from datetime.date
        assert_equal(np.datetime64('1945-03-25'),
                     np.datetime64(datetime.date(1945, 3, 25)))
        assert_equal(np.datetime64('2045-03-25', 'D'),
                     np.datetime64(datetime.date(2045, 3, 25), 'D'))
        # Construction from datetime.datetime
        assert_equal(np.datetime64('1980-01-25T14:36:22.5'),
                     np.datetime64(datetime.datetime(1980, 1, 25,
                                                14, 36, 22, 500000)))

        # Construction with time units from a date is okay
        assert_equal(np.datetime64('1920-03-13', 'h'),
                     np.datetime64('1920-03-13T00'))
        assert_equal(np.datetime64('1920-03', 'm'),
                     np.datetime64('1920-03-01T00:00'))
        assert_equal(np.datetime64('1920', 's'),
                     np.datetime64('1920-01-01T00:00:00'))
        assert_equal(np.datetime64(datetime.date(2045, 3, 25), 'ms'),
                     np.datetime64('2045-03-25T00:00:00.000'))

        # Construction with date units from a datetime is also okay
        assert_equal(np.datetime64('1920-03-13T18', 'D'),
                     np.datetime64('1920-03-13'))
        assert_equal(np.datetime64('1920-03-13T18:33:12', 'M'),
                     np.datetime64('1920-03'))
        assert_equal(np.datetime64('1920-03-13T18:33:12.5', 'Y'),
                     np.datetime64('1920'))

    def test_datetime_scalar_construction_timezone(self):
        # verify that supplying an explicit timezone works, but is deprecated
        with assert_warns(DeprecationWarning):
            assert_equal(np.datetime64('2000-01-01T00Z'),
                         np.datetime64('2000-01-01T00'))
        with assert_warns(DeprecationWarning):
            assert_equal(np.datetime64('2000-01-01T00-08'),
                         np.datetime64('2000-01-01T08'))

    def test_datetime_array_find_type(self):
        dt = np.datetime64('1970-01-01', 'M')
        arr = np.array([dt])
        assert_equal(arr.dtype, np.dtype('M8[M]'))

        # at the moment, we don't automatically convert these to datetime64

        dt = datetime.date(1970, 1, 1)
        arr = np.array([dt])
        assert_equal(arr.dtype, np.dtype('O'))

        dt = datetime.datetime(1970, 1, 1, 12, 30, 40)
        arr = np.array([dt])
        assert_equal(arr.dtype, np.dtype('O'))

        # find "supertype" for non-dates and dates

        b = np.bool_(True)
        dm = np.datetime64('1970-01-01', 'M')
        d = datetime.date(1970, 1, 1)
        dt = datetime.datetime(1970, 1, 1, 12, 30, 40)

        arr = np.array([b, dm])
        assert_equal(arr.dtype, np.dtype('O'))

        arr = np.array([b, d])
        assert_equal(arr.dtype, np.dtype('O'))

        arr = np.array([b, dt])
        assert_equal(arr.dtype, np.dtype('O'))

        arr = np.array([d, d]).astype('datetime64')
        assert_equal(arr.dtype, np.dtype('M8[D]'))

        arr = np.array([dt, dt]).astype('datetime64')
        assert_equal(arr.dtype, np.dtype('M8[us]'))

    @pytest.mark.parametrize("unit", [
    # test all date / time units and use
    # "generic" to select generic unit
    ("Y"), ("M"), ("W"), ("D"), ("h"), ("m"),
    ("s"), ("ms"), ("us"), ("ns"), ("ps"),
    ("fs"), ("as"), ("generic") ])
    def test_timedelta_np_int_construction(self, unit):
        # regression test for gh-7617
        if unit != "generic":
            assert_equal(np.timedelta64(np.int64(123), unit),
                         np.timedelta64(123, unit))
        else:
            assert_equal(np.timedelta64(np.int64(123)),
                         np.timedelta64(123))

    def test_timedelta_scalar_construction(self):
        # Construct with different units
        assert_equal(np.timedelta64(7, 'D'),
                     np.timedelta64(1, 'W'))
        assert_equal(np.timedelta64(120, 's'),
                     np.timedelta64(2, 'm'))

        # Default construction means 0
        assert_equal(np.timedelta64(), np.timedelta64(0))

        # None gets constructed as NaT
        assert_equal(np.timedelta64(None), np.timedelta64('NaT'))

        # Some basic strings and repr
        assert_equal(str(np.timedelta64('NaT')), 'NaT')
        assert_equal(repr(np.timedelta64('NaT')),
                     "numpy.timedelta64('NaT')")
        assert_equal(str(np.timedelta64(3, 's')), '3 seconds')
        assert_equal(repr(np.timedelta64(-3, 's')),
                     "numpy.timedelta64(-3,'s')")
        assert_equal(repr(np.timedelta64(12)),
                     "numpy.timedelta64(12)")

        # 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')
        b = np.array(2, dtype='m8[h]')

        assert_equal(a.dtype, np.dtype('m8[h]'))
        assert_equal(b.dtype, np.dtype('m8[h]'))

        assert_equal(np.timedelta64(a), a)
        assert_equal(np.timedelta64(a).dtype, np.dtype('m8[h]'))

        assert_equal(np.timedelta64(b), a)
        assert_equal(np.timedelta64(b).dtype, np.dtype('m8[h]'))

        assert_equal(np.timedelta64(a, 's'), a)
        assert_equal(np.timedelta64(a, 's').dtype, np.dtype('m8[s]'))

        assert_equal(np.timedelta64(b, 's'), a)
        assert_equal(np.timedelta64(b, 's').dtype, np.dtype('m8[s]'))

        # Construction from datetime.timedelta
        assert_equal(np.timedelta64(5, 'D'),
                     np.timedelta64(datetime.timedelta(days=5)))
        assert_equal(np.timedelta64(102347621, 's'),
                     np.timedelta64(datetime.timedelta(seconds=102347621)))
        assert_equal(np.timedelta64(-10234760000, 'us'),
                     np.timedelta64(datetime.timedelta(
                                            microseconds=-10234760000)))
        assert_equal(np.timedelta64(10234760000, 'us'),
                     np.timedelta64(datetime.timedelta(
                                            microseconds=10234760000)))
        assert_equal(np.timedelta64(1023476, 'ms'),
                     np.timedelta64(datetime.timedelta(milliseconds=1023476)))
        assert_equal(np.timedelta64(10, 'm'),
                     np.timedelta64(datetime.timedelta(minutes=10)))
        assert_equal(np.timedelta64(281, 'h'),
                     np.timedelta64(datetime.timedelta(hours=281)))
        assert_equal(np.timedelta64(28, 'W'),
                     np.timedelta64(datetime.timedelta(weeks=28)))

        # Cannot construct across nonlinear time unit boundaries
        a = np.timedelta64(3, 's')
        assert_raises(TypeError, np.timedelta64, a, 'M')
        assert_raises(TypeError, np.timedelta64, a, 'Y')
        a = np.timedelta64(6, 'M')
        assert_raises(TypeError, np.timedelta64, a, 'D')
        assert_raises(TypeError, np.timedelta64, a, 'h')
        a = np.timedelta64(1, 'Y')
        assert_raises(TypeError, np.timedelta64, a, 'D')
        assert_raises(TypeError, np.timedelta64, a, 'm')
        a = datetime.timedelta(seconds=3)
        assert_raises(TypeError, np.timedelta64, a, 'M')
        assert_raises(TypeError, np.timedelta64, a, 'Y')
        a = datetime.timedelta(weeks=3)
        assert_raises(TypeError, np.timedelta64, a, 'M')
        assert_raises(TypeError, np.timedelta64, a, 'Y')
        a = datetime.timedelta()
        assert_raises(TypeError, np.timedelta64, a, 'M')
        assert_raises(TypeError, np.timedelta64, a, 'Y')

    def test_timedelta_object_array_conversion(self):
        # Regression test for gh-11096
        inputs = [datetime.timedelta(28),
                  datetime.timedelta(30),
                  datetime.timedelta(31)]
        expected = np.array([28, 30, 31], dtype='timedelta64[D]')
        actual = np.array(inputs, dtype='timedelta64[D]')
        assert_equal(expected, actual)

    def test_timedelta_0_dim_object_array_conversion(self):
        # Regression test for gh-11151
        test = np.array(datetime.timedelta(seconds=20))
        actual = test.astype(np.timedelta64)
        # expected value from the array constructor workaround
        # described in above issue
        expected = np.array(datetime.timedelta(seconds=20),
                            np.timedelta64)
        assert_equal(actual, expected)

    def test_timedelta_nat_format(self):
        # gh-17552
        assert_equal('NaT', '{0}'.format(np.timedelta64('nat')))

    def test_timedelta_scalar_construction_units(self):
        # String construction detecting units
        assert_equal(np.datetime64('2010').dtype,
                     np.dtype('M8[Y]'))
        assert_equal(np.datetime64('2010-03').dtype,
                     np.dtype('M8[M]'))
        assert_equal(np.datetime64('2010-03-12').dtype,
                     np.dtype('M8[D]'))
        assert_equal(np.datetime64('2010-03-12T17').dtype,
                     np.dtype('M8[h]'))
        assert_equal(np.datetime64('2010-03-12T17:15').dtype,
                     np.dtype('M8[m]'))
        assert_equal(np.datetime64('2010-03-12T17:15:08').dtype,
                     np.dtype('M8[s]'))

        assert_equal(np.datetime64('2010-03-12T17:15:08.1').dtype,
                     np.dtype('M8[ms]'))
        assert_equal(np.datetime64('2010-03-12T17:15:08.12').dtype,
                     np.dtype('M8[ms]'))
        assert_equal(np.datetime64('2010-03-12T17:15:08.123').dtype,
                     np.dtype('M8[ms]'))

        assert_equal(np.datetime64('2010-03-12T17:15:08.1234').dtype,
                     np.dtype('M8[us]'))
        assert_equal(np.datetime64('2010-03-12T17:15:08.12345').dtype,
                     np.dtype('M8[us]'))
        assert_equal(np.datetime64('2010-03-12T17:15:08.123456').dtype,
                     np.dtype('M8[us]'))

        assert_equal(np.datetime64('1970-01-01T00:00:02.1234567').dtype,
                     np.dtype('M8[ns]'))
        assert_equal(np.datetime64('1970-01-01T00:00:02.12345678').dtype,
                     np.dtype('M8[ns]'))
        assert_equal(np.datetime64('1970-01-01T00:00:02.123456789').dtype,
                     np.dtype('M8[ns]'))

        assert_equal(np.datetime64('1970-01-01T00:00:02.1234567890').dtype,
                     np.dtype('M8[ps]'))
        assert_equal(np.datetime64('1970-01-01T00:00:02.12345678901').dtype,
                     np.dtype('M8[ps]'))
        assert_equal(np.datetime64('1970-01-01T00:00:02.123456789012').dtype,
                     np.dtype('M8[ps]'))

        assert_equal(np.datetime64(
                     '1970-01-01T00:00:02.1234567890123').dtype,
                     np.dtype('M8[fs]'))
        assert_equal(np.datetime64(
                     '1970-01-01T00:00:02.12345678901234').dtype,
                     np.dtype('M8[fs]'))
        assert_equal(np.datetime64(
                     '1970-01-01T00:00:02.123456789012345').dtype,
                     np.dtype('M8[fs]'))

        assert_equal(np.datetime64(
                    '1970-01-01T00:00:02.1234567890123456').dtype,
                     np.dtype('M8[as]'))
        assert_equal(np.datetime64(
                    '1970-01-01T00:00:02.12345678901234567').dtype,
                     np.dtype('M8[as]'))
        assert_equal(np.datetime64(
                    '1970-01-01T00:00:02.123456789012345678').dtype,
                     np.dtype('M8[as]'))

        # Python date object
        assert_equal(np.datetime64(datetime.date(2010, 4, 16)).dtype,
                     np.dtype('M8[D]'))

        # Python datetime object
        assert_equal(np.datetime64(
                        datetime.datetime(2010, 4, 16, 13, 45, 18)).dtype,
                     np.dtype('M8[us]'))

        # 'today' special value
        assert_equal(np.datetime64('today').dtype,
                     np.dtype('M8[D]'))

        # 'now' special value
        assert_equal(np.datetime64('now').dtype,
                     np.dtype('M8[s]'))

    def test_datetime_nat_casting(self):
        a = np.array('NaT', dtype='M8[D]')
        b = np.datetime64('NaT', '[D]')

        # Arrays
        assert_equal(a.astype('M8[s]'), np.array('NaT', dtype='M8[s]'))
        assert_equal(a.astype('M8[ms]'), np.array('NaT', dtype='M8[ms]'))
        assert_equal(a.astype('M8[M]'), np.array('NaT', dtype='M8[M]'))
        assert_equal(a.astype('M8[Y]'), np.array('NaT', dtype='M8[Y]'))
        assert_equal(a.astype('M8[W]'), np.array('NaT', dtype='M8[W]'))

        # Scalars -> Scalars
        assert_equal(np.datetime64(b, '[s]'), np.datetime64('NaT', '[s]'))
        assert_equal(np.datetime64(b, '[ms]'), np.datetime64('NaT', '[ms]'))
        assert_equal(np.datetime64(b, '[M]'), np.datetime64('NaT', '[M]'))
        assert_equal(np.datetime64(b, '[Y]'), np.datetime64('NaT', '[Y]'))
        assert_equal(np.datetime64(b, '[W]'), np.datetime64('NaT', '[W]'))

        # Arrays -> Scalars
        assert_equal(np.datetime64(a, '[s]'), np.datetime64('NaT', '[s]'))
        assert_equal(np.datetime64(a, '[ms]'), np.datetime64('NaT', '[ms]'))
        assert_equal(np.datetime64(a, '[M]'), np.datetime64('NaT', '[M]'))
        assert_equal(np.datetime64(a, '[Y]'), np.datetime64('NaT', '[Y]'))
        assert_equal(np.datetime64(a, '[W]'), np.datetime64('NaT', '[W]'))

        # NaN -> NaT
        nan = np.array([np.nan] * 8)
        fnan = nan.astype('f')
        lnan = nan.astype('g')
        cnan = nan.astype('D')
        cfnan = nan.astype('F')
        clnan = nan.astype('G')

        nat = np.array([np.datetime64('NaT')] * 8)
        assert_equal(nan.astype('M8[ns]'), nat)
        assert_equal(fnan.astype('M8[ns]'), nat)
        assert_equal(lnan.astype('M8[ns]'), nat)
        assert_equal(cnan.astype('M8[ns]'), nat)
        assert_equal(cfnan.astype('M8[ns]'), nat)
        assert_equal(clnan.astype('M8[ns]'), nat)

        nat = np.array([np.timedelta64('NaT')] * 8)
        assert_equal(nan.astype('timedelta64[ns]'), nat)
        assert_equal(fnan.astype('timedelta64[ns]'), nat)
        assert_equal(lnan.astype('timedelta64[ns]'), nat)
        assert_equal(cnan.astype('timedelta64[ns]'), nat)
        assert_equal(cfnan.astype('timedelta64[ns]'), nat)
        assert_equal(clnan.astype('timedelta64[ns]'), nat)

    def test_days_creation(self):
        assert_equal(np.array('1599', dtype='M8[D]').astype('i8'),
                (1600-1970)*365 - (1972-1600)/4 + 3 - 365)
        assert_equal(np.array('1600', dtype='M8[D]').astype('i8'),
                (1600-1970)*365 - (1972-1600)/4 + 3)
        assert_equal(np.array('1601', dtype='M8[D]').astype('i8'),
                (1600-1970)*365 - (1972-1600)/4 + 3 + 366)
        assert_equal(np.array('1900', dtype='M8[D]').astype('i8'),
                (1900-1970)*365 - (1970-1900)//4)
        assert_equal(np.array('1901', dtype='M8[D]').astype('i8'),
                (1900-1970)*365 - (1970-1900)//4 + 365)
        assert_equal(np.array('1967', dtype='M8[D]').astype('i8'), -3*365 - 1)
        assert_equal(np.array('1968', dtype='M8[D]').astype('i8'), -2*365 - 1)
        assert_equal(np.array('1969', dtype='M8[D]').astype('i8'), -1*365)
        assert_equal(np.array('1970', dtype='M8[D]').astype('i8'), 0*365)
        assert_equal(np.array('1971', dtype='M8[D]').astype('i8'), 1*365)
        assert_equal(np.array('1972', dtype='M8[D]').astype('i8'), 2*365)
        assert_equal(np.array('1973', dtype='M8[D]').astype('i8'), 3*365 + 1)
        assert_equal(np.array('1974', dtype='M8[D]').astype('i8'), 4*365 + 1)
        assert_equal(np.array('2000', dtype='M8[D]').astype('i8'),
                 (2000 - 1970)*365 + (2000 - 1972)//4)
        assert_equal(np.array('2001', dtype='M8[D]').astype('i8'),
                 (2000 - 1970)*365 + (2000 - 1972)//4 + 366)
        assert_equal(np.array('2400', dtype='M8[D]').astype('i8'),
                 (2400 - 1970)*365 + (2400 - 1972)//4 - 3)
        assert_equal(np.array('2401', dtype='M8[D]').astype('i8'),
                 (2400 - 1970)*365 + (2400 - 1972)//4 - 3 + 366)

        assert_equal(np.array('1600-02-29', dtype='M8[D]').astype('i8'),
                (1600-1970)*365 - (1972-1600)//4 + 3 + 31 + 28)
        assert_equal(np.array('1600-03-01', dtype='M8[D]').astype('i8'),
                (1600-1970)*365 - (1972-1600)//4 + 3 + 31 + 29)
        assert_equal(np.array('2000-02-29', dtype='M8[D]').astype('i8'),
                 (2000 - 1970)*365 + (2000 - 1972)//4 + 31 + 28)
        assert_equal(np.array('2000-03-01', dtype='M8[D]').astype('i8'),
                 (2000 - 1970)*365 + (2000 - 1972)//4 + 31 + 29)
        assert_equal(np.array('2001-03-22', dtype='M8[D]').astype('i8'),
                 (2000 - 1970)*365 + (2000 - 1972)//4 + 366 + 31 + 28 + 21)

    def test_days_to_pydate(self):
        assert_equal(np.array('1599', dtype='M8[D]').astype('O'),
                    datetime.date(1599, 1, 1))
        assert_equal(np.array('1600', dtype='M8[D]').astype('O'),
                    datetime.date(1600, 1, 1))
        assert_equal(np.array('1601', dtype='M8[D]').astype('O'),
                    datetime.date(1601, 1, 1))
        assert_equal(np.array('1900', dtype='M8[D]').astype('O'),
                    datetime.date(1900, 1, 1))
        assert_equal(np.array('1901', dtype='M8[D]').astype('O'),
                    datetime.date(1901, 1, 1))
        assert_equal(np.array('2000', dtype='M8[D]').astype('O'),
                    datetime.date(2000, 1, 1))
        assert_equal(np.array('2001', dtype='M8[D]').astype('O'),
                    datetime.date(2001, 1, 1))
        assert_equal(np.array('1600-02-29', dtype='M8[D]').astype('O'),
                    datetime.date(1600, 2, 29))
        assert_equal(np.array('1600-03-01', dtype='M8[D]').astype('O'),
                    datetime.date(1600, 3, 1))
        assert_equal(np.array('2001-03-22', dtype='M8[D]').astype('O'),
                    datetime.date(2001, 3, 22))

    def test_dtype_comparison(self):
        assert_(not (np.dtype('M8[us]') == np.dtype('M8[ms]')))
        assert_(np.dtype('M8[us]') != np.dtype('M8[ms]'))
        assert_(np.dtype('M8[2D]') != np.dtype('M8[D]'))
        assert_(np.dtype('M8[D]') != np.dtype('M8[2D]'))

    def test_pydatetime_creation(self):
        a = np.array(['1960-03-12', datetime.date(1960, 3, 12)], dtype='M8[D]')
        assert_equal(a[0], a[1])
        a = np.array(['1999-12-31', datetime.date(1999, 12, 31)], dtype='M8[D]')
        assert_equal(a[0], a[1])
        a = np.array(['2000-01-01', datetime.date(2000, 1, 1)], dtype='M8[D]')
        assert_equal(a[0], a[1])
        # Will fail if the date changes during the exact right moment
        a = np.array(['today', datetime.date.today()], dtype='M8[D]')
        assert_equal(a[0], a[1])
        # datetime.datetime.now() returns local time, not UTC
        #a = np.array(['now', datetime.datetime.now()], dtype='M8[s]')
        #assert_equal(a[0], a[1])

        # we can give a datetime.date time units
        assert_equal(np.array(datetime.date(1960, 3, 12), dtype='M8[s]'),
                     np.array(np.datetime64('1960-03-12T00:00:00')))

    def test_datetime_string_conversion(self):
        a = ['2011-03-16', '1920-01-01', '2013-05-19']
        str_a = np.array(a, dtype='S')
        uni_a = np.array(a, dtype='U')
        dt_a = np.array(a, dtype='M')

        # String to datetime
        assert_equal(dt_a, str_a.astype('M'))
        assert_equal(dt_a.dtype, str_a.astype('M').dtype)
        dt_b = np.empty_like(dt_a)
        dt_b[...] = str_a
        assert_equal(dt_a, dt_b)

        # Datetime to string
        assert_equal(str_a, dt_a.astype('S0'))
        str_b = np.empty_like(str_a)
        str_b[...] = dt_a
        assert_equal(str_a, str_b)

        # Unicode to datetime
        assert_equal(dt_a, uni_a.astype('M'))
        assert_equal(dt_a.dtype, uni_a.astype('M').dtype)
        dt_b = np.empty_like(dt_a)
        dt_b[...] = uni_a
        assert_equal(dt_a, dt_b)

        # Datetime to unicode
        assert_equal(uni_a, dt_a.astype('U'))
        uni_b = np.empty_like(uni_a)
        uni_b[...] = dt_a
        assert_equal(uni_a, uni_b)

        # Datetime to long string - gh-9712
        assert_equal(str_a, dt_a.astype((np.bytes_, 128)))
        str_b = np.empty(str_a.shape, dtype=(np.bytes_, 128))
        str_b[...] = dt_a
        assert_equal(str_a, str_b)

    @pytest.mark.parametrize("time_dtype", ["m8[D]", "M8[Y]"])
    def test_time_byteswapping(self, time_dtype):
        times = np.array(["2017", "NaT"], dtype=time_dtype)
        times_swapped = times.astype(times.dtype.newbyteorder())
        assert_array_equal(times, times_swapped)

        unswapped = times_swapped.view(np.int64).newbyteorder()
        assert_array_equal(unswapped, times.view(np.int64))

    @pytest.mark.parametrize(["time1", "time2"],
            [("M8[s]", "M8[D]"), ("m8[s]", "m8[ns]")])
    def test_time_byteswapped_cast(self, time1, time2):
        dtype1 = np.dtype(time1)
        dtype2 = np.dtype(time2)
        times = np.array(["2017", "NaT"], dtype=dtype1)
        expected = times.astype(dtype2)

        # Test that every byte-swapping combination also returns the same
        # results (previous tests check that this comparison works fine).
        res = times.astype(dtype1.newbyteorder()).astype(dtype2)
        assert_array_equal(res, expected)
        res = times.astype(dtype2.newbyteorder())
        assert_array_equal(res, expected)
        res = times.astype(dtype1.newbyteorder()).astype(dtype2.newbyteorder())
        assert_array_equal(res, expected)

    @pytest.mark.parametrize("time_dtype", ["m8[D]", "M8[Y]"])
    @pytest.mark.parametrize("str_dtype", ["U", "S"])
    def test_datetime_conversions_byteorders(self, str_dtype, time_dtype):
        times = np.array(["2017", "NaT"], dtype=time_dtype)
        # Unfortunately, timedelta does not roundtrip:
        from_strings = np.array(["2017", "NaT"], dtype=str_dtype)
        to_strings = times.astype(str_dtype)  # assume this is correct

        # Check that conversion from times to string works if src is swapped:
        times_swapped = times.astype(times.dtype.newbyteorder())
        res = times_swapped.astype(str_dtype)
        assert_array_equal(res, to_strings)
        # And also if both are swapped:
        res = times_swapped.astype(to_strings.dtype.newbyteorder())
        assert_array_equal(res, to_strings)
        # only destination is swapped:
        res = times.astype(to_strings.dtype.newbyteorder())
        assert_array_equal(res, to_strings)

        # Check that conversion from string to times works if src is swapped:
        from_strings_swapped = from_strings.astype(
                from_strings.dtype.newbyteorder())
        res = from_strings_swapped.astype(time_dtype)
        assert_array_equal(res, times)
        # And if both are swapped:
        res = from_strings_swapped.astype(times.dtype.newbyteorder())
        assert_array_equal(res, times)
        # Only destination is swapped:
        res = from_strings.astype(times.dtype.newbyteorder())
        assert_array_equal(res, times)

    def test_datetime_array_str(self):
        a = np.array(['2011-03-16', '1920-01-01', '2013-05-19'], dtype='M')
        assert_equal(str(a), "['2011-03-16' '1920-01-01' '2013-05-19']")

        a = np.array(['2011-03-16T13:55', '1920-01-01T03:12'], dtype='M')
        assert_equal(np.array2string(a, separator=', ',
                    formatter={'datetime': lambda x:
                            "'%s'" % np.datetime_as_string(x, timezone='UTC')}),
                     "['2011-03-16T13:55Z', '1920-01-01T03:12Z']")

        # Check that one NaT doesn't corrupt subsequent entries
        a = np.array(['2010', 'NaT', '2030']).astype('M')
        assert_equal(str(a), "['2010'  'NaT' '2030']")

    def test_timedelta_array_str(self):
        a = np.array([-1, 0, 100], dtype='m')
        assert_equal(str(a), "[ -1   0 100]")
        a = np.array(['NaT', 'NaT'], dtype='m')
        assert_equal(str(a), "['NaT' 'NaT']")
        # Check right-alignment with NaTs
        a = np.array([-1, 'NaT', 0], dtype='m')
        assert_equal(str(a), "[   -1 'NaT'     0]")
        a = np.array([-1, 'NaT', 1234567], dtype='m')
        assert_equal(str(a), "[     -1   'NaT' 1234567]")

        # Test with other byteorder:
        a = np.array([-1, 'NaT', 1234567], dtype='>m')
        assert_equal(str(a), "[     -1   'NaT' 1234567]")
        a = np.array([-1, 'NaT', 1234567], dtype='<m')
        assert_equal(str(a), "[     -1   'NaT' 1234567]")

    def test_pickle(self):
        # Check that pickle roundtripping works
        for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
            dt = np.dtype('M8[7D]')
            assert_equal(pickle.loads(pickle.dumps(dt, protocol=proto)), dt)
            dt = np.dtype('M8[W]')
            assert_equal(pickle.loads(pickle.dumps(dt, protocol=proto)), dt)
            scalar = np.datetime64('2016-01-01T00:00:00.000000000')
            assert_equal(pickle.loads(pickle.dumps(scalar, protocol=proto)),
                         scalar)
            delta = scalar - np.datetime64('2015-01-01T00:00:00.000000000')
            assert_equal(pickle.loads(pickle.dumps(delta, protocol=proto)),
                         delta)

        # Check that loading pickles from 1.6 works
        pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n" + \
              b"(I4\nS'<'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'D'\np6\n" + \
              b"I7\nI1\nI1\ntp7\ntp8\ntp9\nb."
        assert_equal(pickle.loads(pkl), np.dtype('<M8[7D]'))
        pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n" + \
              b"(I4\nS'<'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'W'\np6\n" + \
              b"I1\nI1\nI1\ntp7\ntp8\ntp9\nb."
        assert_equal(pickle.loads(pkl), np.dtype('<M8[W]'))
        pkl = b"cnumpy\ndtype\np0\n(S'M8'\np1\nI0\nI1\ntp2\nRp3\n" + \
              b"(I4\nS'>'\np4\nNNNI-1\nI-1\nI0\n((dp5\n(S'us'\np6\n" + \
              b"I1\nI1\nI1\ntp7\ntp8\ntp9\nb."
        assert_equal(pickle.loads(pkl), np.dtype('>M8[us]'))

    def test_setstate(self):
        "Verify that datetime dtype __setstate__ can handle bad arguments"
        dt = np.dtype('>M8[us]')
        assert_raises(ValueError, dt.__setstate__, (4, '>', None, None, None, -1, -1, 0, 1))
        assert_(dt.__reduce__()[2] == np.dtype('>M8[us]').__reduce__()[2])
        assert_raises(TypeError, dt.__setstate__, (4, '>', None, None, None, -1, -1, 0, ({}, 'xxx')))
        assert_(dt.__reduce__()[2] == np.dtype('>M8[us]').__reduce__()[2])

    def test_dtype_promotion(self):
        # datetime <op> datetime computes the metadata gcd
        # timedelta <op> timedelta computes the metadata gcd
        for mM in ['m', 'M']:
            assert_equal(
                np.promote_types(np.dtype(mM+'8[2Y]'), np.dtype(mM+'8[2Y]')),
                np.dtype(mM+'8[2Y]'))
            assert_equal(
                np.promote_types(np.dtype(mM+'8[12Y]'), np.dtype(mM+'8[15Y]')),
                np.dtype(mM+'8[3Y]'))
            assert_equal(
                np.promote_types(np.dtype(mM+'8[62M]'), np.dtype(mM+'8[24M]')),
                np.dtype(mM+'8[2M]'))
            assert_equal(
                np.promote_types(np.dtype(mM+'8[1W]'), np.dtype(mM+'8[2D]')),
                np.dtype(mM+'8[1D]'))
            assert_equal(
                np.promote_types(np.dtype(mM+'8[W]'), np.dtype(mM+'8[13s]')),
                np.dtype(mM+'8[s]'))
            assert_equal(
                np.promote_types(np.dtype(mM+'8[13W]'), np.dtype(mM+'8[49s]')),
                np.dtype(mM+'8[7s]'))
        # timedelta <op> timedelta raises when there is no reasonable gcd
        assert_raises(TypeError, np.promote_types,
                            np.dtype('m8[Y]'), np.dtype('m8[D]'))
        assert_raises(TypeError, np.promote_types,
                            np.dtype('m8[M]'), np.dtype('m8[W]'))
        # timedelta and float cannot be safely cast with each other
        assert_raises(TypeError, np.promote_types, "float32", "m8")
        assert_raises(TypeError, np.promote_types, "m8", "float32")
        assert_raises(TypeError, np.promote_types, "uint64", "m8")
        assert_raises(TypeError, np.promote_types, "m8", "uint64")

        # timedelta <op> timedelta may overflow with big unit ranges
        assert_raises(OverflowError, np.promote_types,
                            np.dtype('m8[W]'), np.dtype('m8[fs]'))
        assert_raises(OverflowError, np.promote_types,
                            np.dtype('m8[s]'), np.dtype('m8[as]'))

    def test_cast_overflow(self):
        # gh-4486
        def cast():
            numpy.datetime64("1971-01-01 00:00:00.000000000000000").astype("<M8[D]")
        assert_raises(OverflowError, cast)

        def cast2():
            numpy.datetime64("2014").astype("<M8[fs]")
        assert_raises(OverflowError, cast2)

    def test_pyobject_roundtrip(self):
        # All datetime types should be able to roundtrip through object
        a = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0,
                      -1020040340, -2942398, -1, 0, 1, 234523453, 1199164176],
                                                        dtype=np.int64)
        # With date units
        for unit in ['M8[D]', 'M8[W]', 'M8[M]', 'M8[Y]']:
            b = a.copy().view(dtype=unit)
            b[0] = '-0001-01-01'
            b[1] = '-0001-12-31'
            b[2] = '0000-01-01'
            b[3] = '0001-01-01'
            b[4] = '1969-12-31'
            b[5] = '1970-01-01'
            b[6] = '9999-12-31'
            b[7] = '10000-01-01'
            b[8] = 'NaT'

            assert_equal(b.astype(object).astype(unit), b,
                            "Error roundtripping unit %s" % unit)
        # With time units
        for unit in ['M8[as]', 'M8[16fs]', 'M8[ps]', 'M8[us]',
                     'M8[300as]', 'M8[20us]']:
            b = a.copy().view(dtype=unit)
            b[0] = '-0001-01-01T00'
            b[1] = '-0001-12-31T00'
            b[2] = '0000-01-01T00'
            b[3] = '0001-01-01T00'
            b[4] = '1969-12-31T23:59:59.999999'
            b[5] = '1970-01-01T00'
            b[6] = '9999-12-31T23:59:59.999999'
            b[7] = '10000-01-01T00'
            b[8] = 'NaT'

            assert_equal(b.astype(object).astype(unit), b,
                            "Error roundtripping unit %s" % unit)

    def test_month_truncation(self):
        # Make sure that months are truncating correctly
        assert_equal(np.array('1945-03-01', dtype='M8[M]'),
                     np.array('1945-03-31', dtype='M8[M]'))
        assert_equal(np.array('1969-11-01', dtype='M8[M]'),
             np.array('1969-11-30T23:59:59.99999', dtype='M').astype('M8[M]'))
        assert_equal(np.array('1969-12-01', dtype='M8[M]'),
             np.array('1969-12-31T23:59:59.99999', dtype='M').astype('M8[M]'))
        assert_equal(np.array('1970-01-01', dtype='M8[M]'),
             np.array('1970-01-31T23:59:59.99999', dtype='M').astype('M8[M]'))
        assert_equal(np.array('1980-02-01', dtype='M8[M]'),
             np.array('1980-02-29T23:59:59.99999', dtype='M').astype('M8[M]'))

    def test_different_unit_comparison(self):
        # Check some years with date units
        for unit1 in ['Y', 'M', 'D']:
            dt1 = np.dtype('M8[%s]' % unit1)
            for unit2 in ['Y', 'M', 'D']:
                dt2 = np.dtype('M8[%s]' % unit2)
                assert_equal(np.array('1945', dtype=dt1),
                             np.array('1945', dtype=dt2))
                assert_equal(np.array('1970', dtype=dt1),
                             np.array('1970', dtype=dt2))
                assert_equal(np.array('9999', dtype=dt1),
                             np.array('9999', dtype=dt2))
                assert_equal(np.array('10000', dtype=dt1),
                             np.array('10000-01-01', dtype=dt2))
                assert_equal(np.datetime64('1945', unit1),
                             np.datetime64('1945', unit2))
                assert_equal(np.datetime64('1970', unit1),
                             np.datetime64('1970', unit2))
                assert_equal(np.datetime64('9999', unit1),
                             np.datetime64('9999', unit2))
                assert_equal(np.datetime64('10000', unit1),
                             np.datetime64('10000-01-01', unit2))
        # Check some datetimes with time units
        for unit1 in ['6h', 'h', 'm', 's', '10ms', 'ms', 'us']:
            dt1 = np.dtype('M8[%s]' % unit1)
            for unit2 in ['h', 'm', 's', 'ms', 'us']:
                dt2 = np.dtype('M8[%s]' % unit2)
                assert_equal(np.array('1945-03-12T18', dtype=dt1),
                             np.array('1945-03-12T18', dtype=dt2))
                assert_equal(np.array('1970-03-12T18', dtype=dt1),
                             np.array('1970-03-12T18', dtype=dt2))
                assert_equal(np.array('9999-03-12T18', dtype=dt1),
                             np.array('9999-03-12T18', dtype=dt2))
                assert_equal(np.array('10000-01-01T00', dtype=dt1),
                             np.array('10000-01-01T00', dtype=dt2))
                assert_equal(np.datetime64('1945-03-12T18', unit1),
                             np.datetime64('1945-03-12T18', unit2))
                assert_equal(np.datetime64('1970-03-12T18', unit1),
                             np.datetime64('1970-03-12T18', unit2))
                assert_equal(np.datetime64('9999-03-12T18', unit1),
                             np.datetime64('9999-03-12T18', unit2))
                assert_equal(np.datetime64('10000-01-01T00', unit1),
                             np.datetime64('10000-01-01T00', unit2))
        # Check some days with units that won't overflow
        for unit1 in ['D', '12h', 'h', 'm', 's', '4s', 'ms', 'us']:
            dt1 = np.dtype('M8[%s]' % unit1)
            for unit2 in ['D', 'h', 'm', 's', 'ms', 'us']:
                dt2 = np.dtype('M8[%s]' % unit2)
                assert_(np.equal(np.array('1932-02-17', dtype='M').astype(dt1),
                     np.array('1932-02-17T00:00:00', dtype='M').astype(dt2),
                     casting='unsafe'))
                assert_(np.equal(np.array('10000-04-27', dtype='M').astype(dt1),
                     np.array('10000-04-27T00:00:00', dtype='M').astype(dt2),
                     casting='unsafe'))

        # Shouldn't be able to compare datetime and timedelta
        a = np.array('2012-12-21', dtype='M8[D]')
        b = np.array(3, dtype='m8[D]')
        assert_raises(TypeError, np.less, a, b)
        # not even if "unsafe"
        assert_raises(TypeError, np.less, a, b, casting='unsafe')

    def test_datetime_like(self):
        a = np.array([3], dtype='m8[4D]')
        b = np.array(['2012-12-21'], dtype='M8[D]')

        assert_equal(np.ones_like(a).dtype, a.dtype)
        assert_equal(np.zeros_like(a).dtype, a.dtype)
        assert_equal(np.empty_like(a).dtype, a.dtype)
        assert_equal(np.ones_like(b).dtype, b.dtype)
        assert_equal(np.zeros_like(b).dtype, b.dtype)
        assert_equal(np.empty_like(b).dtype, b.dtype)

    def test_datetime_unary(self):
        for tda, tdb, tdzero, tdone, tdmone in \
                [
                 # One-dimensional arrays
                 (np.array([3], dtype='m8[D]'),
                  np.array([-3], dtype='m8[D]'),
                  np.array([0], dtype='m8[D]'),
                  np.array([1], dtype='m8[D]'),
                  np.array([-1], dtype='m8[D]')),
                 # NumPy scalars
                 (np.timedelta64(3, '[D]'),
                  np.timedelta64(-3, '[D]'),
                  np.timedelta64(0, '[D]'),
                  np.timedelta64(1, '[D]'),
                  np.timedelta64(-1, '[D]'))]:
            # negative ufunc
            assert_equal(-tdb, tda)
            assert_equal((-tdb).dtype, tda.dtype)
            assert_equal(np.negative(tdb), tda)
            assert_equal(np.negative(tdb).dtype, tda.dtype)

            # positive ufunc
            assert_equal(np.positive(tda), tda)
            assert_equal(np.positive(tda).dtype, tda.dtype)
            assert_equal(np.positive(tdb), tdb)
            assert_equal(np.positive(tdb).dtype, tdb.dtype)

            # absolute ufunc
            assert_equal(np.absolute(tdb), tda)
            assert_equal(np.absolute(tdb).dtype, tda.dtype)

            # sign ufunc
            assert_equal(np.sign(tda), tdone)
            assert_equal(np.sign(tdb), tdmone)
            assert_equal(np.sign(tdzero), tdzero)
            assert_equal(np.sign(tda).dtype, tda.dtype)

            # The ufuncs always produce native-endian results
            assert_

    def test_datetime_add(self):
        for dta, dtb, dtc, dtnat, tda, tdb, tdc in \
                    [
                     # One-dimensional arrays
                     (np.array(['2012-12-21'], dtype='M8[D]'),
                      np.array(['2012-12-24'], dtype='M8[D]'),
                      np.array(['2012-12-21T11'], dtype='M8[h]'),
                      np.array(['NaT'], dtype='M8[D]'),
                      np.array([3], dtype='m8[D]'),
                      np.array([11], dtype='m8[h]'),
                      np.array([3*24 + 11], dtype='m8[h]')),
                     # NumPy scalars
                     (np.datetime64('2012-12-21', '[D]'),
                      np.datetime64('2012-12-24', '[D]'),
                      np.datetime64('2012-12-21T11', '[h]'),
                      np.datetime64('NaT', '[D]'),
                      np.timedelta64(3, '[D]'),
                      np.timedelta64(11, '[h]'),
                      np.timedelta64(3*24 + 11, '[h]'))]:
            # m8 + m8
            assert_equal(tda + tdb, tdc)
            assert_equal((tda + tdb).dtype, np.dtype('m8[h]'))
            # m8 + bool
            assert_equal(tdb + True, tdb + 1)
            assert_equal((tdb + True).dtype, np.dtype('m8[h]'))
            # m8 + int
            assert_equal(tdb + 3*24, tdc)
            assert_equal((tdb + 3*24).dtype, np.dtype('m8[h]'))
            # bool + m8
            assert_equal(False + tdb, tdb)
            assert_equal((False + tdb).dtype, np.dtype('m8[h]'))
            # int + m8
            assert_equal(3*24 + tdb, tdc)
            assert_equal((3*24 + tdb).dtype, np.dtype('m8[h]'))
            # M8 + bool
            assert_equal(dta + True, dta + 1)
            assert_equal(dtnat + True, dtnat)
            assert_equal((dta + True).dtype, np.dtype('M8[D]'))
            # M8 + int
            assert_equal(dta + 3, dtb)
            assert_equal(dtnat + 3, dtnat)
            assert_equal((dta + 3).dtype, np.dtype('M8[D]'))
            # bool + M8
            assert_equal(False + dta, dta)
            assert_equal(False + dtnat, dtnat)
            assert_equal((False + dta).dtype, np.dtype('M8[D]'))
            # int + M8
            assert_equal(3 + dta, dtb)
            assert_equal(3 + dtnat, dtnat)
            assert_equal((3 + dta).dtype, np.dtype('M8[D]'))
            # M8 + m8
            assert_equal(dta + tda, dtb)
            assert_equal(dtnat + tda, dtnat)
            assert_equal((dta + tda).dtype, np.dtype('M8[D]'))
            # m8 + M8
            assert_equal(tda + dta, dtb)
            assert_equal(tda + dtnat, dtnat)
            assert_equal((tda + dta).dtype, np.dtype('M8[D]'))

            # In M8 + m8, the result goes to higher precision
            assert_equal(np.add(dta, tdb, casting='unsafe'), dtc)
            assert_equal(np.add(dta, tdb, casting='unsafe').dtype,
                         np.dtype('M8[h]'))
            assert_equal(np.add(tdb, dta, casting='unsafe'), dtc)
            assert_equal(np.add(tdb, dta, casting='unsafe').dtype,
                         np.dtype('M8[h]'))

            # M8 + M8
            assert_raises(TypeError, np.add, dta, dtb)

    def test_datetime_subtract(self):
        for dta, dtb, dtc, dtd, dte, dtnat, tda, tdb, tdc in \
                    [
                     # One-dimensional arrays
                     (np.array(['2012-12-21'], dtype='M8[D]'),
                      np.array(['2012-12-24'], dtype='M8[D]'),
                      np.array(['1940-12-24'], dtype='M8[D]'),
                      np.array(['1940-12-24T00'], dtype='M8[h]'),
                      np.array(['1940-12-23T13'], dtype='M8[h]'),
                      np.array(['NaT'], dtype='M8[D]'),
                      np.array([3], dtype='m8[D]'),
                      np.array([11], dtype='m8[h]'),
                      np.array([3*24 - 11], dtype='m8[h]')),
                     # NumPy scalars
                     (np.datetime64('2012-12-21', '[D]'),
                      np.datetime64('2012-12-24', '[D]'),
                      np.datetime64('1940-12-24', '[D]'),
                      np.datetime64('1940-12-24T00', '[h]'),
                      np.datetime64('1940-12-23T13', '[h]'),
                      np.datetime64('NaT', '[D]'),
                      np.timedelta64(3, '[D]'),
                      np.timedelta64(11, '[h]'),
                      np.timedelta64(3*24 - 11, '[h]'))]:
            # m8 - m8
            assert_equal(tda - tdb, tdc)
            assert_equal((tda - tdb).dtype, np.dtype('m8[h]'))
            assert_equal(tdb - tda, -tdc)
            assert_equal((tdb - tda).dtype, np.dtype('m8[h]'))
            # m8 - bool
            assert_equal(tdc - True, tdc - 1)
            assert_equal((tdc - True).dtype, np.dtype('m8[h]'))
            # m8 - int
            assert_equal(tdc - 3*24, -tdb)
            assert_equal((tdc - 3*24).dtype, np.dtype('m8[h]'))
            # int - m8
            assert_equal(False - tdb, -tdb)
            assert_equal((False - tdb).dtype, np.dtype('m8[h]'))
            # int - m8
            assert_equal(3*24 - tdb, tdc)
            assert_equal((3*24 - tdb).dtype, np.dtype('m8[h]'))
            # M8 - bool
            assert_equal(dtb - True, dtb - 1)
            assert_equal(dtnat - True, dtnat)
            assert_equal((dtb - True).dtype, np.dtype('M8[D]'))
            # M8 - int
            assert_equal(dtb - 3, dta)
            assert_equal(dtnat - 3, dtnat)
            assert_equal((dtb - 3).dtype, np.dtype('M8[D]'))
            # M8 - m8
            assert_equal(dtb - tda, dta)
            assert_equal(dtnat - tda, dtnat)
            assert_equal((dtb - tda).dtype, np.dtype('M8[D]'))

            # In M8 - m8, the result goes to higher precision
            assert_equal(np.subtract(dtc, tdb, casting='unsafe'), dte)
            assert_equal(np.subtract(dtc, tdb, casting='unsafe').dtype,
                         np.dtype('M8[h]'))

            # M8 - M8 with different goes to higher precision
            assert_equal(np.subtract(dtc, dtd, casting='unsafe'),
                         np.timedelta64(0, 'h'))
            assert_equal(np.subtract(dtc, dtd, casting='unsafe').dtype,
                         np.dtype('m8[h]'))
            assert_equal(np.subtract(dtd, dtc, casting='unsafe'),
                         np.timedelta64(0, 'h'))
            assert_equal(np.subtract(dtd, dtc, casting='unsafe').dtype,
                         np.dtype('m8[h]'))

            # m8 - M8
            assert_raises(TypeError, np.subtract, tda, dta)
            # bool - M8
            assert_raises(TypeError, np.subtract, False, dta)
            # int - M8
            assert_raises(TypeError, np.subtract, 3, dta)

    def test_datetime_multiply(self):
        for dta, tda, tdb, tdc in \
                    [
                     # One-dimensional arrays
                     (np.array(['2012-12-21'], dtype='M8[D]'),
                      np.array([6], dtype='m8[h]'),
                      np.array([9], dtype='m8[h]'),
                      np.array([12], dtype='m8[h]')),
                     # NumPy scalars
                     (np.datetime64('2012-12-21', '[D]'),
                      np.timedelta64(6, '[h]'),
                      np.timedelta64(9, '[h]'),
                      np.timedelta64(12, '[h]'))]:
            # m8 * int
            assert_equal(tda * 2, tdc)
            assert_equal((tda * 2).dtype, np.dtype('m8[h]'))
            # int * m8
            assert_equal(2 * tda, tdc)
            assert_equal((2 * tda).dtype, np.dtype('m8[h]'))
            # m8 * float
            assert_equal(tda * 1.5, tdb)
            assert_equal((tda * 1.5).dtype, np.dtype('m8[h]'))
            # float * m8
            assert_equal(1.5 * tda, tdb)
            assert_equal((1.5 * tda).dtype, np.dtype('m8[h]'))

            # m8 * m8
            assert_raises(TypeError, np.multiply, tda, tdb)
            # m8 * M8
            assert_raises(TypeError, np.multiply, dta, tda)
            # M8 * m8
            assert_raises(TypeError, np.multiply, tda, dta)
            # M8 * int
            assert_raises(TypeError, np.multiply, dta, 2)
            # int * M8
            assert_raises(TypeError, np.multiply, 2, dta)
            # M8 * float
            assert_raises(TypeError, np.multiply, dta, 1.5)
            # float * M8
            assert_raises(TypeError, np.multiply, 1.5, dta)

        # NaTs
        with suppress_warnings() as sup:
            sup.filter(RuntimeWarning, "invalid value encountered in multiply")
            nat = np.timedelta64('NaT')
            def check(a, b, res):
                assert_equal(a * b, res)
                assert_equal(b * a, res)
            for tp in (int, float):
                check(nat, tp(2), nat)
                check(nat, tp(0), nat)
            for f in (float('inf'), float('nan')):
                check(np.timedelta64(1), f, nat)
                check(np.timedelta64(0), f, nat)
                check(nat, f, nat)

    @pytest.mark.parametrize("op1, op2, exp", [
        # m8 same units round down
        (np.timedelta64(7, 's'),
         np.timedelta64(4, 's'),
         1),
        # m8 same units round down with negative
        (np.timedelta64(7, 's'),
         np.timedelta64(-4, 's'),
         -2),
        # m8 same units negative no round down
        (np.timedelta64(8, 's'),
         np.timedelta64(-4, 's'),
         -2),
        # m8 different units
        (np.timedelta64(1, 'm'),
         np.timedelta64(31, 's'),
         1),
        # m8 generic units
        (np.timedelta64(1890),
         np.timedelta64(31),
         60),
        # Y // M works
        (np.timedelta64(2, 'Y'),
         np.timedelta64('13', 'M'),
         1),
        # handle 1D arrays
        (np.array([1, 2, 3], dtype='m8'),
         np.array([2], dtype='m8'),
         np.array([0, 1, 1], dtype=np.int64)),
        ])
    def test_timedelta_floor_divide(self, op1, op2, exp):
        assert_equal(op1 // op2, exp)

    @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
    @pytest.mark.parametrize("op1, op2", [
        # div by 0
        (np.timedelta64(10, 'us'),
         np.timedelta64(0, 'us')),
        # div with NaT
        (np.timedelta64('NaT'),
         np.timedelta64(50, 'us')),
        # special case for int64 min
        # in integer floor division
        (np.timedelta64(np.iinfo(np.int64).min),
         np.timedelta64(-1)),
        ])
    def test_timedelta_floor_div_warnings(self, op1, op2):
        with assert_warns(RuntimeWarning):
            actual = op1 // op2
            assert_equal(actual, 0)
            assert_equal(actual.dtype, np.int64)

    @pytest.mark.parametrize("val1, val2", [
        # the smallest integer that can't be represented
        # exactly in a double should be preserved if we avoid
        # casting to double in floordiv operation
        (9007199254740993, 1),
        # stress the alternate floordiv code path where
        # operand signs don't match and remainder isn't 0
        (9007199254740999, -2),
        ])
    def test_timedelta_floor_div_precision(self, val1, val2):
        op1 = np.timedelta64(val1)
        op2 = np.timedelta64(val2)
        actual = op1 // op2
        # Python reference integer floor
        expected = val1 // val2
        assert_equal(actual, expected)

    @pytest.mark.parametrize("val1, val2", [
        # years and months sometimes can't be unambiguously
        # divided for floor division operation
        (np.timedelta64(7, 'Y'),
         np.timedelta64(3, 's')),
        (np.timedelta64(7, 'M'),
         np.timedelta64(1, 'D')),
        ])
    def test_timedelta_floor_div_error(self, val1, val2):
        with assert_raises_regex(TypeError, "common metadata divisor"):
            val1 // val2

    @pytest.mark.parametrize("op1, op2", [
        # reuse the test cases from floordiv
        (np.timedelta64(7, 's'),
         np.timedelta64(4, 's')),
        # m8 same units round down with negative
        (np.timedelta64(7, 's'),
         np.timedelta64(-4, 's')),
        # m8 same units negative no round down
        (np.timedelta64(8, 's'),
         np.timedelta64(-4, 's')),
        # m8 different units
        (np.timedelta64(1, 'm'),
         np.timedelta64(31, 's')),
        # m8 generic units
        (np.timedelta64(1890),
         np.timedelta64(31)),
        # Y // M works
        (np.timedelta64(2, 'Y'),
         np.timedelta64('13', 'M')),
        # handle 1D arrays
        (np.array([1, 2, 3], dtype='m8'),
         np.array([2], dtype='m8')),
        ])
    def test_timedelta_divmod(self, op1, op2):
        expected = (op1 // op2, op1 % op2)
        assert_equal(divmod(op1, op2), expected)

    @pytest.mark.skipif(IS_WASM, reason="does not work in wasm")
    @pytest.mark.parametrize("op1, op2", [
        # reuse cases from floordiv
        # div by 0
        (np.timedelta64(10, 'us'),
         np.timedelta64(0, 'us')),
        # div with NaT
        (np.timedelta64('NaT'),
         np.timedelta64(50, 'us')),
        # special case for int64 min
        # in integer floor division
        (np.timedelta64(np.iinfo(np.int64).min),
         np.timedelta64(-1)),
        ])
    def test_timedelta_divmod_warnings(self, op1, op2):
        with assert_warns(RuntimeWarning):
            expected = (op1 // op2, op1 % op2)
        with assert_warns(RuntimeWarning):
            actual = divmod(op1, op2)
        assert_equal(actual, expected)

    def test_datetime_divide(self):
        for dta, tda, tdb, tdc, tdd in \
                    [
                     # One-dimensional arrays
                     (np.array(['2012-12-21'], dtype='M8[D]'),
                      np.array([6], dtype='m8[h]'),
                      np.array([9], dtype='m8[h]'),
                      np.array([12], dtype='m8[h]'),
                      np.array([6], dtype='m8[m]')),
                     # NumPy scalars
                     (np.datetime64('2012-12-21', '[D]'),
                      np.timedelta64(6, '[h]'),
                      np.timedelta64(9, '[h]'),
                      np.timedelta64(12, '[h]'),
                      np.timedelta64(6, '[m]'))]:
            # m8 / int
            assert_equal(tdc / 2, tda)
            assert_equal((tdc / 2).dtype, np.dtype('m8[h]'))
            # m8 / float
            assert_equal(tda / 0.5, tdc)
            assert_equal((tda / 0.5).dtype, np.dtype('m8[h]'))
            # m8 / m8
            assert_equal(tda / tdb, 6 / 9)
            assert_equal(np.divide(tda, tdb), 6 / 9)
            assert_equal(np.true_divide(tda, tdb), 6 / 9)
            assert_equal(tdb / tda, 9 / 6)
            assert_equal((tda / tdb).dtype, np.dtype('f8'))
            assert_equal(tda / tdd, 60)
            assert_equal(tdd / tda, 1 / 60)

            # int / m8
            assert_raises(TypeError, np.divide, 2, tdb)
            # float / m8
            assert_raises(TypeError, np.divide, 0.5, tdb)
            # m8 / M8
            assert_raises(TypeError, np.divide, dta, tda)
            # M8 / m8
            assert_raises(TypeError, np.divide, tda, dta)
            # M8 / int
            assert_raises(TypeError, np.divide, dta, 2)
            # int / M8
            assert_raises(TypeError, np.divide, 2, dta)
            # M8 / float
            assert_raises(TypeError, np.divide, dta, 1.5)
            # float / M8
            assert_raises(TypeError, np.divide, 1.5, dta)

        # NaTs
        with suppress_warnings() as sup:
            sup.filter(RuntimeWarning,  r".*encountered in divide")
            nat = np.timedelta64('NaT')
            for tp in (int, float):
                assert_equal(np.timedelta64(1) / tp(0), nat)
                assert_equal(np.timedelta64(0) / tp(0), nat)
                assert_equal(nat / tp(0), nat)
                assert_equal(nat / tp(2), nat)
            # Division by inf
            assert_equal(np.timedelta64(1) / float('inf'), np.timedelta64(0))
            assert_equal(np.timedelta64(0) / float('inf'), np.timedelta64(0))
            assert_equal(nat / float('inf'), nat)
            # Division by nan
            assert_equal(np.timedelta64(1) / float('nan'), nat)
            assert_equal(np.timedelta64(0) / float('nan'), nat)
            assert_equal(nat / float('nan'), nat)

    def test_datetime_compare(self):
        # Test all the comparison operators
        a = np.datetime64('2000-03-12T18:00:00.000000')
        b = np.array(['2000-03-12T18:00:00.000000',
                      '2000-03-12T17:59:59.999999',
                      '2000-03-12T18:00:00.000001',
                      '1970-01-11T12:00:00.909090',
                      '2016-01-11T12:00:00.909090'],
                      dtype='datetime64[us]')
        assert_equal(np.equal(a, b), [1, 0, 0, 0, 0])
        assert_equal(np.not_equal(a, b), [0, 1, 1, 1, 1])
        assert_equal(np.less(a, b), [0, 0, 1, 0, 1])
        assert_equal(np.less_equal(a, b), [1, 0, 1, 0, 1])
        assert_equal(np.greater(a, b), [0, 1, 0, 1, 0])
        assert_equal(np.greater_equal(a, b), [1, 1, 0, 1, 0])

    def test_datetime_compare_nat(self):
        dt_nat = np.datetime64('NaT', 'D')
        dt_other = np.datetime64('2000-01-01')
        td_nat = np.timedelta64('NaT', 'h')
        td_other = np.timedelta64(1, 'h')

        for op in [np.equal, np.less, np.less_equal,
                   np.greater, np.greater_equal]:
            assert_(not op(dt_nat, dt_nat))
            assert_(not op(dt_nat, dt_other))
            assert_(not op(dt_other, dt_nat))

            assert_(not op(td_nat, td_nat))
            assert_(not op(td_nat, td_other))
            assert_(not op(td_other, td_nat))

        assert_(np.not_equal(dt_nat, dt_nat))
        assert_(np.not_equal(dt_nat, dt_other))
        assert_(np.not_equal(dt_other, dt_nat))

        assert_(np.not_equal(td_nat, td_nat))
        assert_(np.not_equal(td_nat, td_other))
        assert_(np.not_equal(td_other, td_nat))

    def test_datetime_minmax(self):
        # The metadata of the result should become the GCD
        # of the operand metadata
        a = np.array('1999-03-12T13', dtype='M8[2m]')
        b = np.array('1999-03-12T12', dtype='M8[s]')
        assert_equal(np.minimum(a, b), b)
        assert_equal(np.minimum(a, b).dtype, np.dtype('M8[s]'))
        assert_equal(np.fmin(a, b), b)
        assert_equal(np.fmin(a, b).dtype, np.dtype('M8[s]'))
        assert_equal(np.maximum(a, b), a)
        assert_equal(np.maximum(a, b).dtype, np.dtype('M8[s]'))
        assert_equal(np.fmax(a, b), a)
        assert_equal(np.fmax(a, b).dtype, np.dtype('M8[s]'))
        # Viewed as integers, the comparison is opposite because
        # of the units chosen
        assert_equal(np.minimum(a.view('i8'), b.view('i8')), a.view('i8'))

        # Interaction with NaT
        a = np.array('1999-03-12T13', dtype='M8[2m]')
        dtnat = np.array('NaT', dtype='M8[h]')
        assert_equal(np.minimum(a, dtnat), dtnat)
        assert_equal(np.minimum(dtnat, a), dtnat)
        assert_equal(np.maximum(a, dtnat), dtnat)
        assert_equal(np.maximum(dtnat, a), dtnat)
        assert_equal(np.fmin(dtnat, a), a)
        assert_equal(np.fmin(a, dtnat), a)
        assert_equal(np.fmax(dtnat, a), a)
        assert_equal(np.fmax(a, dtnat), a)

        # Also do timedelta
        a = np.array(3, dtype='m8[h]')
        b = np.array(3*3600 - 3, dtype='m8[s]')
        assert_equal(np.minimum(a, b), b)
        assert_equal(np.minimum(a, b).dtype, np.dtype('m8[s]'))
        assert_equal(np.fmin(a, b), b)
        assert_equal(np.fmin(a, b).dtype, np.dtype('m8[s]'))
        assert_equal(np.maximum(a, b), a)
        assert_equal(np.maximum(a, b).dtype, np.dtype('m8[s]'))
        assert_equal(np.fmax(a, b), a)
        assert_equal(np.fmax(a, b).dtype, np.dtype('m8[s]'))
        # Viewed as integers, the comparison is opposite because
        # of the units chosen
        assert_equal(np.minimum(a.view('i8'), b.view('i8')), a.view('i8'))

        # should raise between datetime and timedelta
        #
        # TODO: Allowing unsafe casting by
        #       default in ufuncs strikes again... :(
        a = np.array(3, dtype='m8[h]')
        b = np.array('1999-03-12T12', dtype='M8[s]')
        #assert_raises(TypeError, np.minimum, a, b)
        #assert_raises(TypeError, np.maximum, a, b)
        #assert_raises(TypeError, np.fmin, a, b)
        #assert_raises(TypeError, np.fmax, a, b)
        assert_raises(TypeError, np.minimum, a, b, casting='same_kind')
        assert_raises(TypeError, np.maximum, a, b, casting='same_kind')
        assert_raises(TypeError, np.fmin, a, b, casting='same_kind')
        assert_raises(TypeError, np.fmax, a, b, casting='same_kind')

    def test_hours(self):
        t = np.ones(3, dtype='M8[s]')
        t[0] = 60*60*24 + 60*60*10
        assert_(t[0].item().hour == 10)

    def test_divisor_conversion_year(self):
        assert_(np.dtype('M8[Y/4]') == np.dtype('M8[3M]'))
        assert_(np.dtype('M8[Y/13]') == np.dtype('M8[4W]'))
        assert_(np.dtype('M8[3Y/73]') == np.dtype('M8[15D]'))

    def test_divisor_conversion_month(self):
        assert_(np.dtype('M8[M/2]') == np.dtype('M8[2W]'))
        assert_(np.dtype('M8[M/15]') == np.dtype('M8[2D]'))
        assert_(np.dtype('M8[3M/40]') == np.dtype('M8[54h]'))

    def test_divisor_conversion_week(self):
        assert_(np.dtype('m8[W/7]') == np.dtype('m8[D]'))
        assert_(np.dtype('m8[3W/14]') == np.dtype('m8[36h]'))
        assert_(np.dtype('m8[5W/140]') == np.dtype('m8[360m]'))

    def test_divisor_conversion_day(self):
        assert_(np.dtype('M8[D/12]') == np.dtype('M8[2h]'))
        assert_(np.dtype('M8[D/120]') == np.dtype('M8[12m]'))
        assert_(np.dtype('M8[3D/960]') == np.dtype('M8[270s]'))

    def test_divisor_conversion_hour(self):
        assert_(np.dtype('m8[h/30]') == np.dtype('m8[2m]'))
        assert_(np.dtype('m8[3h/300]') == np.dtype('m8[36s]'))

    def test_divisor_conversion_minute(self):
        assert_(np.dtype('m8[m/30]') == np.dtype('m8[2s]'))
        assert_(np.dtype('m8[3m/300]') == np.dtype('m8[600ms]'))

    def test_divisor_conversion_second(self):
        assert_(np.dtype('m8[s/100]') == np.dtype('m8[10ms]'))
        assert_(np.dtype('m8[3s/10000]') == np.dtype('m8[300us]'))

    def test_divisor_conversion_fs(self):
        assert_(np.dtype('M8[fs/100]') == np.dtype('M8[10as]'))
        assert_raises(ValueError, lambda: np.dtype('M8[3fs/10000]'))

    def test_divisor_conversion_as(self):
        assert_raises(ValueError, lambda: np.dtype('M8[as/10]'))

    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[s]')),
                     np.array(['1980-02-29 01:02:03'], np.dtype('M8[s]')))
        # Allow positive years
        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[s]')),
                     np.array(['-1980-02-29 01:02:03'], np.dtype('M8[s]')))
        # UTC specifier
        with assert_warns(DeprecationWarning):
            assert_equal(
                np.array(['+1980-02-29T01:02:03'], np.dtype('M8[s]')),
                np.array(['+1980-02-29 01:02:03Z'], np.dtype('M8[s]')))
        with assert_warns(DeprecationWarning):
            assert_equal(
                np.array(['-1980-02-29T01:02:03'], np.dtype('M8[s]')),
                np.array(['-1980-02-29 01:02:03Z'], np.dtype('M8[s]')))
        # Time zone offset
        with assert_warns(DeprecationWarning):
            assert_equal(
                np.array(['1980-02-29T02:02:03'], np.dtype('M8[s]')),
                np.array(['1980-02-29 00:32:03-0130'], np.dtype('M8[s]')))
        with assert_warns(DeprecationWarning):
            assert_equal(
                np.array(['1980-02-28T22:32:03'], np.dtype('M8[s]')),
                np.array(['1980-02-29 00:02:03+01:30'], np.dtype('M8[s]')))
        with assert_warns(DeprecationWarning):
            assert_equal(
                np.array(['1980-02-29T02:32:03.506'], np.dtype('M8[s]')),
                np.array(['1980-02-29 00:32:03.506-02'], np.dtype('M8[s]')))
        with assert_warns(DeprecationWarning):
            assert_equal(np.datetime64('1977-03-02T12:30-0230'),
                         np.datetime64('1977-03-02T15:00'))

    def test_string_parser_error_check(self):
        # Arbitrary bad string
        assert_raises(ValueError, np.array, ['badvalue'], np.dtype('M8[us]'))
        # Character after year must be '-'
        assert_raises(ValueError, np.array, ['1980X'], np.dtype('M8[us]'))
        # Cannot have trailing '-'
        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[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[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[us]'))
        # Cannot have trailing '-'
        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[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[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[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[us]'))
        assert_raises(ValueError, np.array, ['1980-02-03T24:01'],
                                                        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[us]'))
        # Minutes must be in range [0, 59]
        assert_raises(ValueError, np.array, ['1980-02-03 01:-1'],
                                                        np.dtype('M8[us]'))
        assert_raises(ValueError, np.array, ['1980-02-03 01:60'],
                                                        np.dtype('M8[us]'))
        # No trailing ':'
        assert_raises(ValueError, np.array, ['1980-02-03 01:60:'],
                                                        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[us]'))
        assert_raises(ValueError, np.array, ['1980-02-03 01:01:60'],
                                                        np.dtype('M8[us]'))
        # Timezone offset must within a reasonable range
        with assert_warns(DeprecationWarning):
            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00+0661'],
                                                            np.dtype('M8[us]'))
        with assert_warns(DeprecationWarning):
            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00+2500'],
                                                            np.dtype('M8[us]'))
        with assert_warns(DeprecationWarning):
            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-0070'],
                                                            np.dtype('M8[us]'))
        with assert_warns(DeprecationWarning):
            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-3000'],
                                                            np.dtype('M8[us]'))
        with assert_warns(DeprecationWarning):
            assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-25:00'],
                                                            np.dtype('M8[us]'))

    def test_creation_overflow(self):
        date = '1980-03-23 20:00:00'
        timesteps = np.array([date], dtype='datetime64[s]')[0].astype(np.int64)
        for unit in ['ms', 'us', 'ns']:
            timesteps *= 1000
            x = np.array([date], dtype='datetime64[%s]' % unit)

            assert_equal(timesteps, x[0].astype(np.int64),
                         err_msg='Datetime conversion error for unit %s' % unit)

        assert_equal(x[0].astype(np.int64), 322689600000000000)

        # gh-13062
        with pytest.raises(OverflowError):
            np.datetime64(2**64, 'D')
        with pytest.raises(OverflowError):
            np.timedelta64(2**64, 'D')

    def test_datetime_as_string(self):
        # Check all the units with default string conversion
        date = '1959-10-13'
        datetime = '1959-10-13T12:34:56.789012345678901234'

        assert_equal(np.datetime_as_string(np.datetime64(date, 'Y')),
                     '1959')
        assert_equal(np.datetime_as_string(np.datetime64(date, 'M')),
                     '1959-10')
        assert_equal(np.datetime_as_string(np.datetime64(date, 'D')),
                     '1959-10-13')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'h')),
                     '1959-10-13T12')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'm')),
                     '1959-10-13T12:34')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 's')),
                     '1959-10-13T12:34:56')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ms')),
                     '1959-10-13T12:34:56.789')
        for us in ['us', 'μs', b'us']:  # check non-ascii and bytes too
            assert_equal(np.datetime_as_string(np.datetime64(datetime, us)),
                         '1959-10-13T12:34:56.789012')

        datetime = '1969-12-31T23:34:56.789012345678901234'

        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ns')),
                     '1969-12-31T23:34:56.789012345')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ps')),
                     '1969-12-31T23:34:56.789012345678')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'fs')),
                     '1969-12-31T23:34:56.789012345678901')

        datetime = '1969-12-31T23:59:57.789012345678901234'

        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'as')),
                     datetime)
        datetime = '1970-01-01T00:34:56.789012345678901234'

        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ns')),
                     '1970-01-01T00:34:56.789012345')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'ps')),
                     '1970-01-01T00:34:56.789012345678')
        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'fs')),
                     '1970-01-01T00:34:56.789012345678901')

        datetime = '1970-01-01T00:00:05.789012345678901234'

        assert_equal(np.datetime_as_string(np.datetime64(datetime, 'as')),
                     datetime)

        # String conversion with the unit= parameter
        a = np.datetime64('2032-07-18T12:23:34.123456', 'us')
        assert_equal(np.datetime_as_string(a, unit='Y', casting='unsafe'),
                            '2032')
        assert_equal(np.datetime_as_string(a, unit='M', casting='unsafe'),
                            '2032-07')
        assert_equal(np.datetime_as_string(a, unit='W', casting='unsafe'),
                            '2032-07-18')
        assert_equal(np.datetime_as_string(a, unit='D', casting='unsafe'),
                            '2032-07-18')
        assert_equal(np.datetime_as_string(a, unit='h'), '2032-07-18T12')
        assert_equal(np.datetime_as_string(a, unit='m'),
                            '2032-07-18T12:23')
        assert_equal(np.datetime_as_string(a, unit='s'),
                            '2032-07-18T12:23:34')
        assert_equal(np.datetime_as_string(a, unit='ms'),
                            '2032-07-18T12:23:34.123')
        assert_equal(np.datetime_as_string(a, unit='us'),
                            '2032-07-18T12:23:34.123456')
        assert_equal(np.datetime_as_string(a, unit='ns'),
                            '2032-07-18T12:23:34.123456000')
        assert_equal(np.datetime_as_string(a, unit='ps'),
                            '2032-07-18T12:23:34.123456000000')
        assert_equal(np.datetime_as_string(a, unit='fs'),
                            '2032-07-18T12:23:34.123456000000000')
        assert_equal(np.datetime_as_string(a, unit='as'),
                            '2032-07-18T12:23:34.123456000000000000')

        # unit='auto' parameter
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T12:23:34.123456', 'us'), unit='auto'),
                '2032-07-18T12:23:34.123456')
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T12:23:34.12', 'us'), unit='auto'),
                '2032-07-18T12:23:34.120')
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T12:23:34', 'us'), unit='auto'),
                '2032-07-18T12:23:34')
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T12:23:00', 'us'), unit='auto'),
                '2032-07-18T12:23')
        # 'auto' doesn't split up hour and minute
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T12:00:00', 'us'), unit='auto'),
                '2032-07-18T12:00')
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-18T00:00:00', 'us'), unit='auto'),
                '2032-07-18')
        # 'auto' doesn't split up the date
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-07-01T00:00:00', 'us'), unit='auto'),
                '2032-07-01')
        assert_equal(np.datetime_as_string(
                np.datetime64('2032-01-01T00:00:00', 'us'), unit='auto'),
                '2032-01-01')

    @pytest.mark.skipif(not _has_pytz, reason="The pytz module is not available.")
    def test_datetime_as_string_timezone(self):
        # timezone='local' vs 'UTC'
        a = np.datetime64('2010-03-15T06:30', 'm')
        assert_equal(np.datetime_as_string(a),
                '2010-03-15T06:30')
        assert_equal(np.datetime_as_string(a, timezone='naive'),
                '2010-03-15T06:30')
        assert_equal(np.datetime_as_string(a, timezone='UTC'),
                '2010-03-15T06:30Z')
        assert_(np.datetime_as_string(a, timezone='local') !=
                '2010-03-15T06:30')

        b = np.datetime64('2010-02-15T06:30', 'm')

        assert_equal(np.datetime_as_string(a, timezone=tz('US/Central')),
                     '2010-03-15T01:30-0500')
        assert_equal(np.datetime_as_string(a, timezone=tz('US/Eastern')),
                     '2010-03-15T02:30-0400')
        assert_equal(np.datetime_as_string(a, timezone=tz('US/Pacific')),
                     '2010-03-14T23:30-0700')

        assert_equal(np.datetime_as_string(b, timezone=tz('US/Central')),
                     '2010-02-15T00:30-0600')
        assert_equal(np.datetime_as_string(b, timezone=tz('US/Eastern')),
                     '2010-02-15T01:30-0500')
        assert_equal(np.datetime_as_string(b, timezone=tz('US/Pacific')),
                     '2010-02-14T22:30-0800')

        # Dates to strings with a timezone attached is disabled by default
        assert_raises(TypeError, np.datetime_as_string, a, unit='D',
                           timezone=tz('US/Pacific'))
        # Check that we can print out the date in the specified time zone
        assert_equal(np.datetime_as_string(a, unit='D',
                           timezone=tz('US/Pacific'), casting='unsafe'),
                     '2010-03-14')
        assert_equal(np.datetime_as_string(b, unit='D',
                           timezone=tz('US/Central'), casting='unsafe'),
                     '2010-02-15')

    def test_datetime_arange(self):
        # With two datetimes provided as strings
        a = np.arange('2010-01-05', '2010-01-10', dtype='M8[D]')
        assert_equal(a.dtype, np.dtype('M8[D]'))
        assert_equal(a,
            np.array(['2010-01-05', '2010-01-06', '2010-01-07',
                      '2010-01-08', '2010-01-09'], dtype='M8[D]'))

        a = np.arange('1950-02-10', '1950-02-06', -1, dtype='M8[D]')
        assert_equal(a.dtype, np.dtype('M8[D]'))
        assert_equal(a,
            np.array(['1950-02-10', '1950-02-09', '1950-02-08',
                      '1950-02-07'], dtype='M8[D]'))

        # Unit should be detected as months here
        a = np.arange('1969-05', '1970-05', 2, dtype='M8')
        assert_equal(a.dtype, np.dtype('M8[M]'))
        assert_equal(a,
            np.datetime64('1969-05') + np.arange(12, step=2))

        # datetime, integer|timedelta works as well
        # produces arange (start, start + stop) in this case
        a = np.arange('1969', 18, 3, dtype='M8')
        assert_equal(a.dtype, np.dtype('M8[Y]'))
        assert_equal(a,
            np.datetime64('1969') + np.arange(18, step=3))
        a = np.arange('1969-12-19', 22, np.timedelta64(2), dtype='M8')
        assert_equal(a.dtype, np.dtype('M8[D]'))
        assert_equal(a,
            np.datetime64('1969-12-19') + np.arange(22, step=2))

        # Step of 0 is disallowed
        assert_raises(ValueError, np.arange, np.datetime64('today'),
                                np.datetime64('today') + 3, 0)
        # Promotion across nonlinear unit boundaries is disallowed
        assert_raises(TypeError, np.arange, np.datetime64('2011-03-01', 'D'),
                                np.timedelta64(5, 'M'))
        assert_raises(TypeError, np.arange,
                                np.datetime64('2012-02-03T14', 's'),
                                np.timedelta64(5, 'Y'))

    def test_datetime_arange_no_dtype(self):
        d = np.array('2010-01-04', dtype="M8[D]")
        assert_equal(np.arange(d, d + 1), d)
        assert_raises(ValueError, np.arange, d)

    def test_timedelta_arange(self):
        a = np.arange(3, 10, dtype='m8')
        assert_equal(a.dtype, np.dtype('m8'))
        assert_equal(a, np.timedelta64(0) + np.arange(3, 10))

        a = np.arange(np.timedelta64(3, 's'), 10, 2, dtype='m8')
        assert_equal(a.dtype, np.dtype('m8[s]'))
        assert_equal(a, np.timedelta64(0, 's') + np.arange(3, 10, 2))

        # Step of 0 is disallowed
        assert_raises(ValueError, np.arange, np.timedelta64(0),
                                np.timedelta64(5), 0)
        # Promotion across nonlinear unit boundaries is disallowed
        assert_raises(TypeError, np.arange, np.timedelta64(0, 'D'),
                                np.timedelta64(5, 'M'))
        assert_raises(TypeError, np.arange, np.timedelta64(0, 'Y'),
                                np.timedelta64(5, 'D'))

    @pytest.mark.parametrize("val1, val2, expected", [
        # case from gh-12092
        (np.timedelta64(7, 's'),
         np.timedelta64(3, 's'),
         np.timedelta64(1, 's')),
        # negative value cases
        (np.timedelta64(3, 's'),
         np.timedelta64(-2, 's'),
         np.timedelta64(-1, 's')),
        (np.timedelta64(-3, 's'),
         np.timedelta64(2, 's'),
         np.timedelta64(1, 's')),
        # larger value cases
        (np.timedelta64(17, 's'),
         np.timedelta64(22, 's'),
         np.timedelta64(17, 's')),
        (np.timedelta64(22, 's'),
         np.timedelta64(17, 's'),
         np.timedelta64(5, 's')),
        # different units
        (np.timedelta64(1, 'm'),
         np.timedelta64(57, 's'),
         np.timedelta64(3, 's')),
        (np.timedelta64(1, 'us'),
         np.timedelta64(727, 'ns'),
         np.timedelta64(273, 'ns')),
        # NaT is propagated
        (np.timedelta64('NaT'),
         np.timedelta64(50, 'ns'),
         np.timedelta64('NaT')),
        # Y % M works
        (np.timedelta64(2, 'Y'),
         np.timedelta64(22, 'M'),
         np.timedelta64(2, 'M')),
        ])
    def test_timedelta_modulus(self, val1, val2, expected):
        assert_equal(val1 % val2, expected)

    @pytest.mark.parametrize("val1, val2", [
        # years and months sometimes can't be unambiguously
        # divided for modulus operation
        (np.timedelta64(7, 'Y'),
         np.timedelta64(3, 's')),
        (np.timedelta64(7, 'M'),
         np.timedelta64(1, 'D')),
        ])
    def test_timedelta_modulus_error(self, val1, val2):
        with assert_raises_regex(TypeError, "common metadata divisor"):
            val1 % val2

    @pytest.mark.skipif(IS_WASM, reason="fp errors don't work in wasm")
    def test_timedelta_modulus_div_by_zero(self):
        with assert_warns(RuntimeWarning):
            actual = np.timedelta64(10, 's') % np.timedelta64(0, 's')
            assert_equal(actual, np.timedelta64('NaT'))

    @pytest.mark.parametrize("val1, val2", [
        # cases where one operand is not
        # timedelta64
        (np.timedelta64(7, 'Y'),
         15,),
        (7.5,
         np.timedelta64(1, 'D')),
        ])
    def test_timedelta_modulus_type_resolution(self, val1, val2):
        # NOTE: some of the operations may be supported
        # in the future
        with assert_raises_regex(TypeError,
                                 "'remainder' cannot use operands with types"):
            val1 % val2

    def test_timedelta_arange_no_dtype(self):
        d = np.array(5, dtype="m8[D]")
        assert_equal(np.arange(d, d + 1), d)
        assert_equal(np.arange(d), np.arange(0, d))

    def test_datetime_maximum_reduce(self):
        a = np.array(['2010-01-02', '1999-03-14', '1833-03'], dtype='M8[D]')
        assert_equal(np.maximum.reduce(a).dtype, np.dtype('M8[D]'))
        assert_equal(np.maximum.reduce(a),
                     np.datetime64('2010-01-02'))

        a = np.array([1, 4, 0, 7, 2], dtype='m8[s]')
        assert_equal(np.maximum.reduce(a).dtype, np.dtype('m8[s]'))
        assert_equal(np.maximum.reduce(a),
                     np.timedelta64(7, 's'))

    def test_timedelta_correct_mean(self):
        # test mainly because it worked only via a bug in that allowed:
        # `timedelta.sum(dtype="f8")` to ignore the dtype request.
        a = np.arange(1000, dtype="m8[s]")
        assert_array_equal(a.mean(), a.sum() / len(a))

    def test_datetime_no_subtract_reducelike(self):
        # subtracting two datetime64 works, but we cannot reduce it, since
        # the result of that subtraction will have a different dtype.
        arr = np.array(["2021-12-02", "2019-05-12"], dtype="M8[ms]")
        msg = r"the resolved dtypes are not compatible"

        with pytest.raises(TypeError, match=msg):
            np.subtract.reduce(arr)

        with pytest.raises(TypeError, match=msg):
            np.subtract.accumulate(arr)

        with pytest.raises(TypeError, match=msg):
            np.subtract.reduceat(arr, [0])

    def test_datetime_busday_offset(self):
        # First Monday in June
        assert_equal(
            np.busday_offset('2011-06', 0, roll='forward', weekmask='Mon'),
            np.datetime64('2011-06-06'))
        # Last Monday in June
        assert_equal(
            np.busday_offset('2011-07', -1, roll='forward', weekmask='Mon'),
            np.datetime64('2011-06-27'))
        assert_equal(
            np.busday_offset('2011-07', -1, roll='forward', weekmask='Mon'),
            np.datetime64('2011-06-27'))

        # Default M-F business days, different roll modes
        assert_equal(np.busday_offset('2010-08', 0, roll='backward'),
                     np.datetime64('2010-07-30'))
        assert_equal(np.busday_offset('2010-08', 0, roll='preceding'),
                     np.datetime64('2010-07-30'))
        assert_equal(np.busday_offset('2010-08', 0, roll='modifiedpreceding'),
                     np.datetime64('2010-08-02'))
        assert_equal(np.busday_offset('2010-08', 0, roll='modifiedfollowing'),
                     np.datetime64('2010-08-02'))
        assert_equal(np.busday_offset('2010-08', 0, roll='forward'),
                     np.datetime64('2010-08-02'))
        assert_equal(np.busday_offset('2010-08', 0, roll='following'),
                     np.datetime64('2010-08-02'))
        assert_equal(np.busday_offset('2010-10-30', 0, roll='following'),
                     np.datetime64('2010-11-01'))
        assert_equal(
                np.busday_offset('2010-10-30', 0, roll='modifiedfollowing'),
                np.datetime64('2010-10-29'))
        assert_equal(
                np.busday_offset('2010-10-30', 0, roll='modifiedpreceding'),
                np.datetime64('2010-10-29'))
        assert_equal(
                np.busday_offset('2010-10-16', 0, roll='modifiedfollowing'),
                np.datetime64('2010-10-18'))
        assert_equal(
                np.busday_offset('2010-10-16', 0, roll='modifiedpreceding'),
                np.datetime64('2010-10-15'))
        # roll='raise' by default
        assert_raises(ValueError, np.busday_offset, '2011-06-04', 0)

        # Bigger offset values
        assert_equal(np.busday_offset('2006-02-01', 25),
                     np.datetime64('2006-03-08'))
        assert_equal(np.busday_offset('2006-03-08', -25),
                     np.datetime64('2006-02-01'))
        assert_equal(np.busday_offset('2007-02-25', 11, weekmask='SatSun'),
                     np.datetime64('2007-04-07'))
        assert_equal(np.busday_offset('2007-04-07', -11, weekmask='SatSun'),
                     np.datetime64('2007-02-25'))

        # NaT values when roll is not raise
        assert_equal(np.busday_offset(np.datetime64('NaT'), 1, roll='nat'),
                     np.datetime64('NaT'))
        assert_equal(np.busday_offset(np.datetime64('NaT'), 1, roll='following'),
                     np.datetime64('NaT'))
        assert_equal(np.busday_offset(np.datetime64('NaT'), 1, roll='preceding'),
                     np.datetime64('NaT'))

    def test_datetime_busdaycalendar(self):
        # Check that it removes NaT, duplicates, and weekends
        # and sorts the result.
        bdd = np.busdaycalendar(
            holidays=['NaT', '2011-01-17', '2011-03-06', 'NaT',
                       '2011-12-26', '2011-05-30', '2011-01-17'])
        assert_equal(bdd.holidays,
            np.array(['2011-01-17', '2011-05-30', '2011-12-26'], dtype='M8'))
        # 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
        assert_equal(
            np.busday_offset('2011-11-10', 1, holidays=['2011-11-11']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-04', 5, holidays=['2011-11-11']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-10', 5, holidays=['2011-11-11']),
            np.datetime64('2011-11-18'))
        assert_equal(
            np.busday_offset('2011-11-14', -1, holidays=['2011-11-11']),
            np.datetime64('2011-11-10'))
        assert_equal(
            np.busday_offset('2011-11-18', -5, holidays=['2011-11-11']),
            np.datetime64('2011-11-10'))
        assert_equal(
            np.busday_offset('2011-11-14', -5, holidays=['2011-11-11']),
            np.datetime64('2011-11-04'))
        # With the holiday appearing twice
        assert_equal(
            np.busday_offset('2011-11-10', 1,
                holidays=['2011-11-11', '2011-11-11']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-14', -1,
                holidays=['2011-11-11', '2011-11-11']),
            np.datetime64('2011-11-10'))
        # With a NaT holiday
        assert_equal(
            np.busday_offset('2011-11-10', 1,
                holidays=['2011-11-11', 'NaT']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-14', -1,
                holidays=['NaT', '2011-11-11']),
            np.datetime64('2011-11-10'))
        # With another holiday after
        assert_equal(
            np.busday_offset('2011-11-10', 1,
                holidays=['2011-11-11', '2011-11-24']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-14', -1,
                holidays=['2011-11-11', '2011-11-24']),
            np.datetime64('2011-11-10'))
        # With another holiday before
        assert_equal(
            np.busday_offset('2011-11-10', 1,
                holidays=['2011-10-10', '2011-11-11']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-14', -1,
                holidays=['2011-10-10', '2011-11-11']),
            np.datetime64('2011-11-10'))
        # With another holiday before and after
        assert_equal(
            np.busday_offset('2011-11-10', 1,
                holidays=['2011-10-10', '2011-11-11', '2011-11-24']),
            np.datetime64('2011-11-14'))
        assert_equal(
            np.busday_offset('2011-11-14', -1,
                holidays=['2011-10-10', '2011-11-11', '2011-11-24']),
            np.datetime64('2011-11-10'))

        # A bigger forward jump across more than one week/holiday
        holidays = ['2011-10-10', '2011-11-11', '2011-11-24',
                  '2011-12-25', '2011-05-30', '2011-02-21',
                  '2011-12-26', '2012-01-02']
        bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays)
        assert_equal(
            np.busday_offset('2011-10-03', 4, holidays=holidays),
            np.busday_offset('2011-10-03', 4))
        assert_equal(
            np.busday_offset('2011-10-03', 5, holidays=holidays),
            np.busday_offset('2011-10-03', 5 + 1))
        assert_equal(
            np.busday_offset('2011-10-03', 27, holidays=holidays),
            np.busday_offset('2011-10-03', 27 + 1))
        assert_equal(
            np.busday_offset('2011-10-03', 28, holidays=holidays),
            np.busday_offset('2011-10-03', 28 + 2))
        assert_equal(
            np.busday_offset('2011-10-03', 35, holidays=holidays),
            np.busday_offset('2011-10-03', 35 + 2))
        assert_equal(
            np.busday_offset('2011-10-03', 36, holidays=holidays),
            np.busday_offset('2011-10-03', 36 + 3))
        assert_equal(
            np.busday_offset('2011-10-03', 56, holidays=holidays),
            np.busday_offset('2011-10-03', 56 + 3))
        assert_equal(
            np.busday_offset('2011-10-03', 57, holidays=holidays),
            np.busday_offset('2011-10-03', 57 + 4))
        assert_equal(
            np.busday_offset('2011-10-03', 60, holidays=holidays),
            np.busday_offset('2011-10-03', 60 + 4))
        assert_equal(
            np.busday_offset('2011-10-03', 61, holidays=holidays),
            np.busday_offset('2011-10-03', 61 + 5))
        assert_equal(
            np.busday_offset('2011-10-03', 61, busdaycal=bdd),
            np.busday_offset('2011-10-03', 61 + 5))
        # A bigger backward jump across more than one week/holiday
        assert_equal(
            np.busday_offset('2012-01-03', -1, holidays=holidays),
            np.busday_offset('2012-01-03', -1 - 1))
        assert_equal(
            np.busday_offset('2012-01-03', -4, holidays=holidays),
            np.busday_offset('2012-01-03', -4 - 1))
        assert_equal(
            np.busday_offset('2012-01-03', -5, holidays=holidays),
            np.busday_offset('2012-01-03', -5 - 2))
        assert_equal(
            np.busday_offset('2012-01-03', -25, holidays=holidays),
            np.busday_offset('2012-01-03', -25 - 2))
        assert_equal(
            np.busday_offset('2012-01-03', -26, holidays=holidays),
            np.busday_offset('2012-01-03', -26 - 3))
        assert_equal(
            np.busday_offset('2012-01-03', -33, holidays=holidays),
            np.busday_offset('2012-01-03', -33 - 3))
        assert_equal(
            np.busday_offset('2012-01-03', -34, holidays=holidays),
            np.busday_offset('2012-01-03', -34 - 4))
        assert_equal(
            np.busday_offset('2012-01-03', -56, holidays=holidays),
            np.busday_offset('2012-01-03', -56 - 4))
        assert_equal(
            np.busday_offset('2012-01-03', -57, holidays=holidays),
            np.busday_offset('2012-01-03', -57 - 5))
        assert_equal(
            np.busday_offset('2012-01-03', -57, busdaycal=bdd),
            np.busday_offset('2012-01-03', -57 - 5))

        # Can't supply both a weekmask/holidays and busdaycal
        assert_raises(ValueError, np.busday_offset, '2012-01-03', -15,
                        weekmask='1111100', busdaycal=bdd)
        assert_raises(ValueError, np.busday_offset, '2012-01-03', -15,
                        holidays=holidays, busdaycal=bdd)

        # Roll with the holidays
        assert_equal(
            np.busday_offset('2011-12-25', 0,
                roll='forward', holidays=holidays),
            np.datetime64('2011-12-27'))
        assert_equal(
            np.busday_offset('2011-12-26', 0,
                roll='forward', holidays=holidays),
            np.datetime64('2011-12-27'))
        assert_equal(
            np.busday_offset('2011-12-26', 0,
                roll='backward', holidays=holidays),
            np.datetime64('2011-12-23'))
        assert_equal(
            np.busday_offset('2012-02-27', 0,
                roll='modifiedfollowing',
                holidays=['2012-02-27', '2012-02-26', '2012-02-28',
                          '2012-03-01', '2012-02-29']),
            np.datetime64('2012-02-24'))
        assert_equal(
            np.busday_offset('2012-03-06', 0,
                roll='modifiedpreceding',
                holidays=['2012-03-02', '2012-03-03', '2012-03-01',
                          '2012-03-05', '2012-03-07', '2012-03-06']),
            np.datetime64('2012-03-08'))

    def test_datetime_busday_holidays_count(self):
        holidays = ['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24',
                    '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17',
                    '2011-12-26', '2012-01-02', '2011-02-21', '2011-05-30',
                    '2011-07-01', '2011-07-04', '2011-09-05', '2011-10-10']
        bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays)

        # Validate against busday_offset broadcast against
        # a range of offsets
        dates = np.busday_offset('2011-01-01', np.arange(366),
                        roll='forward', busdaycal=bdd)
        assert_equal(np.busday_count('2011-01-01', dates, busdaycal=bdd),
                     np.arange(366))
        # Returns negative value when reversed
        # -1 since the '2011-01-01' is not a busday
        assert_equal(np.busday_count(dates, '2011-01-01', busdaycal=bdd),
                     -np.arange(366) - 1)

        # 2011-12-31 is a saturday
        dates = np.busday_offset('2011-12-31', -np.arange(366),
                        roll='forward', busdaycal=bdd)
        # only the first generated date is in the future of 2011-12-31
        expected = np.arange(366)
        expected[0] = -1
        assert_equal(np.busday_count(dates, '2011-12-31', busdaycal=bdd),
                     expected)
        # Returns negative value when reversed
        expected = -np.arange(366)+1
        expected[0] = 0
        assert_equal(np.busday_count('2011-12-31', dates, busdaycal=bdd),
                     expected)

        # Can't supply both a weekmask/holidays and busdaycal
        assert_raises(ValueError, np.busday_offset, '2012-01-03', '2012-02-03',
                        weekmask='1111100', busdaycal=bdd)
        assert_raises(ValueError, np.busday_offset, '2012-01-03', '2012-02-03',
                        holidays=holidays, busdaycal=bdd)

        # Number of Mondays in March 2011
        assert_equal(np.busday_count('2011-03', '2011-04', weekmask='Mon'), 4)
        # Returns negative value when reversed
        assert_equal(np.busday_count('2011-04', '2011-03', weekmask='Mon'), -4)

        sunday = np.datetime64('2023-03-05')
        monday = sunday + 1
        friday = sunday + 5
        saturday = sunday + 6
        assert_equal(np.busday_count(sunday, monday), 0)
        assert_equal(np.busday_count(monday, sunday), -1)

        assert_equal(np.busday_count(friday, saturday), 1)
        assert_equal(np.busday_count(saturday, friday), 0)


    def test_datetime_is_busday(self):
        holidays = ['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24',
                    '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17',
                    '2011-12-26', '2012-01-02', '2011-02-21', '2011-05-30',
                    '2011-07-01', '2011-07-04', '2011-09-05', '2011-10-10',
                    'NaT']
        bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays)

        # Weekend/weekday tests
        assert_equal(np.is_busday('2011-01-01'), False)
        assert_equal(np.is_busday('2011-01-02'), False)
        assert_equal(np.is_busday('2011-01-03'), True)

        # All the holidays are not business days
        assert_equal(np.is_busday(holidays, busdaycal=bdd),
                     np.zeros(len(holidays), dtype='?'))

    def test_datetime_y2038(self):
        # Test parsing on either side of the Y2038 boundary
        a = np.datetime64('2038-01-19T03:14:07')
        assert_equal(a.view(np.int64), 2**31 - 1)
        a = np.datetime64('2038-01-19T03:14:08')
        assert_equal(a.view(np.int64), 2**31)

        # Test parsing on either side of the Y2038 boundary with
        # a manually specified timezone offset
        with assert_warns(DeprecationWarning):
            a = np.datetime64('2038-01-19T04:14:07+0100')
            assert_equal(a.view(np.int64), 2**31 - 1)
        with assert_warns(DeprecationWarning):
            a = np.datetime64('2038-01-19T04:14:08+0100')
            assert_equal(a.view(np.int64), 2**31)

        # Test parsing a date after Y2038
        a = np.datetime64('2038-01-20T13:21:14')
        assert_equal(str(a), '2038-01-20T13:21:14')

    def test_isnat(self):
        assert_(np.isnat(np.datetime64('NaT', 'ms')))
        assert_(np.isnat(np.datetime64('NaT', 'ns')))
        assert_(not np.isnat(np.datetime64('2038-01-19T03:14:07')))

        assert_(np.isnat(np.timedelta64('NaT', "ms")))
        assert_(not np.isnat(np.timedelta64(34, "ms")))

        res = np.array([False, False, True])
        for unit in ['Y', 'M', 'W', 'D',
                     'h', 'm', 's', 'ms', 'us',
                     'ns', 'ps', 'fs', 'as']:
            arr = np.array([123, -321, "NaT"], dtype='<datetime64[%s]' % unit)
            assert_equal(np.isnat(arr), res)
            arr = np.array([123, -321, "NaT"], dtype='>datetime64[%s]' % unit)
            assert_equal(np.isnat(arr), res)
            arr = np.array([123, -321, "NaT"], dtype='<timedelta64[%s]' % unit)
            assert_equal(np.isnat(arr), res)
            arr = np.array([123, -321, "NaT"], dtype='>timedelta64[%s]' % unit)
            assert_equal(np.isnat(arr), res)

    def test_isnat_error(self):
        # Test that only datetime dtype arrays are accepted
        for t in np.typecodes["All"]:
            if t in np.typecodes["Datetime"]:
                continue
            assert_raises(TypeError, np.isnat, np.zeros(10, t))

    def test_isfinite_scalar(self):
        assert_(not np.isfinite(np.datetime64('NaT', 'ms')))
        assert_(not np.isfinite(np.datetime64('NaT', 'ns')))
        assert_(np.isfinite(np.datetime64('2038-01-19T03:14:07')))

        assert_(not np.isfinite(np.timedelta64('NaT', "ms")))
        assert_(np.isfinite(np.timedelta64(34, "ms")))

    @pytest.mark.parametrize('unit', ['Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms',
                                      'us', 'ns', 'ps', 'fs', 'as'])
    @pytest.mark.parametrize('dstr', ['<datetime64[%s]', '>datetime64[%s]',
                                      '<timedelta64[%s]', '>timedelta64[%s]'])
    def test_isfinite_isinf_isnan_units(self, unit, dstr):
        '''check isfinite, isinf, isnan for all units of <M, >M, <m, >m dtypes
        '''
        arr_val = [123, -321, "NaT"]
        arr = np.array(arr_val,  dtype= dstr % unit)
        pos = np.array([True, True,  False])
        neg = np.array([False, False,  True])
        false = np.array([False, False,  False])
        assert_equal(np.isfinite(arr), pos)
        assert_equal(np.isinf(arr), false)
        assert_equal(np.isnan(arr), neg)

    def test_assert_equal(self):
        assert_raises(AssertionError, assert_equal,
                np.datetime64('nat'), np.timedelta64('nat'))

    def test_corecursive_input(self):
        # construct a co-recursive list
        a, b = [], []
        a.append(b)
        b.append(a)
        obj_arr = np.array([None])
        obj_arr[0] = a

        # At some point this caused a stack overflow (gh-11154). Now raises
        # ValueError since the nested list cannot be converted to a datetime.
        assert_raises(ValueError, obj_arr.astype, 'M8')
        assert_raises(ValueError, obj_arr.astype, 'm8')

    @pytest.mark.parametrize("shape", [(), (1,)])
    def test_discovery_from_object_array(self, shape):
        arr = np.array("2020-10-10", dtype=object).reshape(shape)
        res = np.array("2020-10-10", dtype="M8").reshape(shape)
        assert res.dtype == np.dtype("M8[D]")
        assert_equal(arr.astype("M8"), res)
        arr[...] = np.bytes_("2020-10-10")  # try a numpy string type
        assert_equal(arr.astype("M8"), res)
        arr = arr.astype("S")
        assert_equal(arr.astype("S").astype("M8"), res)

    @pytest.mark.parametrize("time_unit", [
        "Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", "fs", "as",
        # compound units
        "10D", "2M",
    ])
    def test_limit_symmetry(self, time_unit):
        """
        Dates should have symmetric limits around the unix epoch at +/-np.int64
        """
        epoch = np.datetime64(0, time_unit)
        latest = np.datetime64(np.iinfo(np.int64).max, time_unit)
        earliest = np.datetime64(-np.iinfo(np.int64).max, time_unit)

        # above should not have overflowed
        assert earliest < epoch < latest

    @pytest.mark.parametrize("time_unit", [
        "Y", "M",
        pytest.param("W", marks=pytest.mark.xfail(reason="gh-13197")),
        "D", "h", "m",
        "s", "ms", "us", "ns", "ps", "fs", "as",
        pytest.param("10D", marks=pytest.mark.xfail(reason="similar to gh-13197")),
    ])
    @pytest.mark.parametrize("sign", [-1, 1])
    def test_limit_str_roundtrip(self, time_unit, sign):
        """
        Limits should roundtrip when converted to strings.

        This tests the conversion to and from npy_datetimestruct.
        """
        # TODO: add absolute (gold standard) time span limit strings
        limit = np.datetime64(np.iinfo(np.int64).max * sign, time_unit)

        # Convert to string and back. Explicit unit needed since the day and
        # week reprs are not distinguishable.
        limit_via_str = np.datetime64(str(limit), time_unit)
        assert limit_via_str == limit


class TestDateTimeData:

    def test_basic(self):
        a = np.array(['1980-03-23'], dtype=np.datetime64)
        assert_equal(np.datetime_data(a.dtype), ('D', 1))

    def test_bytes(self):
        # byte units are converted to unicode
        dt = np.datetime64('2000', (b'ms', 5))
        assert np.datetime_data(dt.dtype) == ('ms', 5)

        dt = np.datetime64('2000', b'5ms')
        assert np.datetime_data(dt.dtype) == ('ms', 5)

    def test_non_ascii(self):
        # μs is normalized to μ
        dt = np.datetime64('2000', ('μs', 5))
        assert np.datetime_data(dt.dtype) == ('us', 5)

        dt = np.datetime64('2000', '5μs')
        assert np.datetime_data(dt.dtype) == ('us', 5)


def test_comparisons_return_not_implemented():
    # GH#17017

    class custom:
        __array_priority__ = 10000

    obj = custom()

    dt = np.datetime64('2000', 'ns')
    td = dt - dt

    for item in [dt, td]:
        assert item.__eq__(obj) is NotImplemented
        assert item.__ne__(obj) is NotImplemented
        assert item.__le__(obj) is NotImplemented
        assert item.__lt__(obj) is NotImplemented
        assert item.__ge__(obj) is NotImplemented
        assert item.__gt__(obj) is NotImplemented

Youez - 2016 - github.com/yon3zu
LinuXploit