* Converts an npy_datetimestruct to an (almost) ISO 8601 * NULL-terminated string. If the string fits in the space exactly, * it leaves out the NULL terminator and returns success. * * The differences from ISO 8601 are the 'NaT' string, and * the number of year digits is >= 4 instead of strictly 4. * * If 'local' is non-zero, it produces a string in local time with * a +-#### timezone offs
| 884 | * string was too short). |
| 885 | */ |
| 886 | NPY_NO_EXPORT int |
| 887 | make_iso_8601_datetime(npy_datetimestruct *dts, char *outstr, npy_intp outlen, |
| 888 | int local, int utc, NPY_DATETIMEUNIT base, int tzoffset, |
| 889 | NPY_CASTING casting) |
| 890 | { |
| 891 | npy_datetimestruct dts_local; |
| 892 | int timezone_offset = 0; |
| 893 | |
| 894 | char *substr = outstr; |
| 895 | npy_intp sublen = outlen; |
| 896 | npy_intp tmplen; |
| 897 | |
| 898 | /* Handle NaT, and treat a datetime with generic units as NaT */ |
| 899 | if (dts->year == NPY_DATETIME_NAT || base == NPY_FR_GENERIC) { |
| 900 | if (outlen < 3) { |
| 901 | goto string_too_short; |
| 902 | } |
| 903 | outstr[0] = 'N'; |
| 904 | outstr[1] = 'a'; |
| 905 | outstr[2] = 'T'; |
| 906 | if (outlen > 3) { |
| 907 | outstr[3] = '\0'; |
| 908 | } |
| 909 | |
| 910 | return 0; |
| 911 | } |
| 912 | |
| 913 | /* |
| 914 | * Only do local time within a reasonable year range. The years |
| 915 | * earlier than 1970 are not made local, because the Windows API |
| 916 | * raises an error when they are attempted (see the comments above the |
| 917 | * get_localtime() function). For consistency, this |
| 918 | * restriction is applied to all platforms. |
| 919 | * |
| 920 | * Note that this only affects how the datetime becomes a string. |
| 921 | * The result is still completely unambiguous, it only means |
| 922 | * that datetimes outside this range will not include a time zone |
| 923 | * when they are printed. |
| 924 | */ |
| 925 | if ((dts->year < 1970 || dts->year >= 10000) && tzoffset == -1) { |
| 926 | local = 0; |
| 927 | } |
| 928 | |
| 929 | /* Automatically detect a good unit */ |
| 930 | if (base == NPY_FR_ERROR) { |
| 931 | base = lossless_unit_from_datetimestruct(dts); |
| 932 | /* |
| 933 | * If there's a timezone, use at least minutes precision, |
| 934 | * and never split up hours and minutes by default |
| 935 | */ |
| 936 | if ((base < NPY_FR_m && local) || base == NPY_FR_h) { |
| 937 | base = NPY_FR_m; |
| 938 | } |
| 939 | /* Don't split up dates by default */ |
| 940 | else if (base < NPY_FR_D) { |
| 941 | base = NPY_FR_D; |
| 942 | } |
| 943 | } |
no test coverage detected