Left: | ||
Right: |
OLD | NEW |
---|---|
1 /* C implementation for the date/time type documented at | 1 /* C implementation for the date/time type documented at |
2 * http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage | 2 * http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage |
3 */ | 3 */ |
4 | 4 |
5 #define PY_SSIZE_T_CLEAN | 5 #define PY_SSIZE_T_CLEAN |
6 | 6 |
7 #include "Python.h" | 7 #include "Python.h" |
8 #include "modsupport.h" | 8 #include "modsupport.h" |
9 #include "structmember.h" | 9 #include "structmember.h" |
10 | 10 |
11 #include <time.h> | 11 #include <time.h> |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
96 * 1 <= M <= 12 | 96 * 1 <= M <= 12 |
97 */ | 97 */ |
98 #define MONTH_IS_SANE(M) ((unsigned int)(M) - 1 < 12) | 98 #define MONTH_IS_SANE(M) ((unsigned int)(M) - 1 < 12) |
99 | 99 |
100 /* Forward declarations. */ | 100 /* Forward declarations. */ |
101 static PyTypeObject PyDateTime_DateType; | 101 static PyTypeObject PyDateTime_DateType; |
102 static PyTypeObject PyDateTime_DateTimeType; | 102 static PyTypeObject PyDateTime_DateTimeType; |
103 static PyTypeObject PyDateTime_DeltaType; | 103 static PyTypeObject PyDateTime_DeltaType; |
104 static PyTypeObject PyDateTime_TimeType; | 104 static PyTypeObject PyDateTime_TimeType; |
105 static PyTypeObject PyDateTime_TZInfoType; | 105 static PyTypeObject PyDateTime_TZInfoType; |
106 static PyTypeObject PyDateTime_UTCType; | |
106 | 107 |
107 /* --------------------------------------------------------------------------- | 108 /* --------------------------------------------------------------------------- |
108 * Math utilities. | 109 * Math utilities. |
109 */ | 110 */ |
110 | 111 |
111 /* k = i+j overflows iff k differs in sign from both inputs, | 112 /* k = i+j overflows iff k differs in sign from both inputs, |
112 * iff k^i has sign bit set and k^j has sign bit set, | 113 * iff k^i has sign bit set and k^j has sign bit set, |
113 * iff (k^i)&(k^j) has sign bit set. | 114 * iff (k^i)&(k^j) has sign bit set. |
114 */ | 115 */ |
115 #define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \ | 116 #define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \ |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
744 SET_TD_DAYS(self, days); | 745 SET_TD_DAYS(self, days); |
745 SET_TD_SECONDS(self, seconds); | 746 SET_TD_SECONDS(self, seconds); |
746 SET_TD_MICROSECONDS(self, microseconds); | 747 SET_TD_MICROSECONDS(self, microseconds); |
747 } | 748 } |
748 return (PyObject *) self; | 749 return (PyObject *) self; |
749 } | 750 } |
750 | 751 |
751 #define new_delta(d, s, us, normalize) \ | 752 #define new_delta(d, s, us, normalize) \ |
752 new_delta_ex(d, s, us, normalize, &PyDateTime_DeltaType) | 753 new_delta_ex(d, s, us, normalize, &PyDateTime_DeltaType) |
753 | 754 |
755 static PyObject * | |
756 new_utc_ex(PyTypeObject *type) | |
757 { | |
758 return type->tp_alloc(type, 0); | |
759 } | |
760 | |
761 #define new_utc() \ | |
762 new_utc_ex(&PyDateTime_UTCType) | |
763 | |
754 /* --------------------------------------------------------------------------- | 764 /* --------------------------------------------------------------------------- |
755 * tzinfo helpers. | 765 * tzinfo helpers. |
756 */ | 766 */ |
757 | 767 |
758 /* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not | 768 /* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not |
759 * raise TypeError and return -1. | 769 * raise TypeError and return -1. |
760 */ | 770 */ |
761 static int | 771 static int |
762 check_tzinfo_subclass(PyObject *p) | 772 check_tzinfo_subclass(PyObject *p) |
763 { | 773 { |
(...skipping 2275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3039 0, /* tp_dict */ | 3049 0, /* tp_dict */ |
3040 0, /* tp_descr_get */ | 3050 0, /* tp_descr_get */ |
3041 0, /* tp_descr_set */ | 3051 0, /* tp_descr_set */ |
3042 0, /* tp_dictoffset */ | 3052 0, /* tp_dictoffset */ |
3043 0, /* tp_init */ | 3053 0, /* tp_init */ |
3044 0, /* tp_alloc */ | 3054 0, /* tp_alloc */ |
3045 PyType_GenericNew, /* tp_new */ | 3055 PyType_GenericNew, /* tp_new */ |
3046 0, /* tp_free */ | 3056 0, /* tp_free */ |
3047 }; | 3057 }; |
3048 | 3058 |
3059 static int | |
3060 utc_init(PyObject *self) | |
brett.cannon
2009/02/27 04:12:29
This function is never used.
| |
3061 { | |
3062 return 0; | |
3063 } | |
3064 | |
3065 static PyObject * | |
3066 utc_tzname(PyObject *self, PyObject *dt) | |
3067 { | |
3068 return PyString_FromString("UTC"); | |
3069 } | |
3070 | |
3071 static PyObject * | |
3072 utc_utcoffset(PyObject *self, PyObject *dt) | |
3073 { | |
3074 return new_delta(0, 0, 0, 0); | |
3075 } | |
3076 | |
3077 static PyObject * | |
3078 utc_dst(PyObject *self, PyObject *dt) | |
3079 { | |
3080 return new_delta(0, 0, 0, 0); | |
3081 } | |
3082 | |
3083 static PyMethodDef utc_methods[] = { | |
3084 | |
3085 {"tzname", (PyCFunction)utc_tzname, METH_O, | |
brett.cannon
2009/02/27 04:12:29
Ditch the tab spacing.
| |
3086 PyDoc_STR("Always 'UTC'.")}, | |
3087 | |
3088 {"utcoffset", (PyCFunction)utc_utcoffset, METH_O, | |
3089 PyDoc_STR("Always 0 minutes.")}, | |
3090 | |
3091 {"dst", (PyCFunction)utc_dst, METH_O, | |
3092 PyDoc_STR("Always 0 minutes.")}, | |
3093 | |
3094 {NULL, NULL} | |
3095 }; | |
3096 | |
3097 static char utc_doc[] = | |
3098 PyDoc_STR("UTC timezone class."); | |
brett.cannon
2009/02/27 04:12:29
Mention it is an implementation of tzinfo.
| |
3099 | |
3100 statichere PyTypeObject PyDateTime_UTCType = { | |
3101 PyObject_HEAD_INIT(NULL) | |
3102 0, /* ob_size */ | |
3103 "datetime.UTC", /* tp_name */ | |
3104 sizeof(PyDateTime_UTC), /* tp_basicsize */ | |
3105 0, /* tp_itemsize */ | |
3106 0, /* tp_dealloc */ | |
3107 0, /* tp_print */ | |
3108 0, /* tp_getattr */ | |
3109 0, /* tp_setattr */ | |
3110 0, /* tp_compare */ | |
3111 0, /* tp_repr */ | |
3112 0, /* tp_as_number */ | |
3113 0, /* tp_as_sequence */ | |
3114 0, /* tp_as_mapping */ | |
3115 0, /* tp_hash */ | |
3116 0, /* tp_call */ | |
3117 0, /* tp_str */ | |
3118 0, /* tp_getattro */ | |
3119 0, /* tp_setattro */ | |
3120 0, /* tp_as_buffer */ | |
3121 Py_TPFLAGS_DEFAULT, /* tp_flags */ | |
3122 utc_doc, /* tp_doc */ | |
3123 0, /* tp_traverse */ | |
3124 0, /* tp_clear */ | |
3125 0, /* tp_richcompare */ | |
3126 0, /* tp_weaklistoffset */ | |
3127 0, /* tp_iter */ | |
3128 0, /* tp_iternext */ | |
3129 utc_methods, /* tp_methods */ | |
3130 0, /* tp_members */ | |
3131 0, /* tp_getset */ | |
3132 &PyDateTime_TZInfoType, /* tp_base */ | |
3133 0, /* tp_dict */ | |
3134 0, /* tp_descr_get */ | |
3135 0, /* tp_descr_set */ | |
3136 0, /* tp_dictoffset */ | |
3137 0, /* tp_init */ | |
3138 0, /* tp_alloc */ | |
3139 PyType_GenericNew, /* tp_new */ | |
3140 }; | |
3141 | |
3049 /* | 3142 /* |
3050 * PyDateTime_Time implementation. | 3143 * PyDateTime_Time implementation. |
3051 */ | 3144 */ |
3052 | 3145 |
3053 /* Accessor properties. | 3146 /* Accessor properties. |
3054 */ | 3147 */ |
3055 | 3148 |
3056 static PyObject * | 3149 static PyObject * |
3057 time_hour(PyDateTime_Time *self, void *unused) | 3150 time_hour(PyDateTime_Time *self, void *unused) |
3058 { | 3151 { |
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3835 self = PyObject_CallMethod(tzinfo, "fromutc", "O", self); | 3928 self = PyObject_CallMethod(tzinfo, "fromutc", "O", self); |
3836 Py_DECREF(temp); | 3929 Py_DECREF(temp); |
3837 } | 3930 } |
3838 return self; | 3931 return self; |
3839 } | 3932 } |
3840 | 3933 |
3841 /* Return best possible UTC time -- this isn't constrained by the | 3934 /* Return best possible UTC time -- this isn't constrained by the |
3842 * precision of a timestamp. | 3935 * precision of a timestamp. |
3843 */ | 3936 */ |
3844 static PyObject * | 3937 static PyObject * |
3845 datetime_utcnow(PyObject *cls, PyObject *dummy) | 3938 datetime_utcnow(PyObject *cls, PyObject *args, PyObject *kw) |
3846 { | 3939 { |
3847 » return datetime_best_possible(cls, gmtime, Py_None); | 3940 PyObject *utc = Py_None; |
3941 PyObject *tz_aware = Py_False; | |
3942 static char *keywords[] = {"tz_aware", NULL}; | |
3943 ·· | |
3944 » if (! PyArg_ParseTupleAndKeywords(args, kw, "|b", | |
3945 » » » » » keywords, &tz_aware)) | |
3946 » » return NULL; | |
3947 if (tz_aware == Py_True) | |
brett.cannon
2009/02/27 04:12:29
Use PyObject_IsTrue() instead of checking for Py_T
| |
3948 utc = new_utc(); | |
brett.cannon
2009/02/27 04:12:29
Check for errors on the return value.
| |
3949 | |
3950 » return datetime_best_possible(cls, gmtime, utc); | |
3848 } | 3951 } |
3849 | 3952 |
3850 /* Return new local datetime from timestamp (Python timestamp -- a double). */ | 3953 /* Return new local datetime from timestamp (Python timestamp -- a double). */ |
3851 static PyObject * | 3954 static PyObject * |
3852 datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw) | 3955 datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw) |
3853 { | 3956 { |
3854 PyObject *self; | 3957 PyObject *self; |
3855 double timestamp; | 3958 double timestamp; |
3856 PyObject *tzinfo = Py_None; | 3959 PyObject *tzinfo = Py_None; |
3857 static char *keywords[] = {"timestamp", "tz", NULL}; | 3960 static char *keywords[] = {"timestamp", "tz", NULL}; |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4560 | 4663 |
4561 static PyMethodDef datetime_methods[] = { | 4664 static PyMethodDef datetime_methods[] = { |
4562 | 4665 |
4563 /* Class methods: */ | 4666 /* Class methods: */ |
4564 | 4667 |
4565 {"now", (PyCFunction)datetime_now, | 4668 {"now", (PyCFunction)datetime_now, |
4566 METH_VARARGS | METH_KEYWORDS | METH_CLASS, | 4669 METH_VARARGS | METH_KEYWORDS | METH_CLASS, |
4567 PyDoc_STR("[tz] -> new datetime with tz's local day and time.")}, | 4670 PyDoc_STR("[tz] -> new datetime with tz's local day and time.")}, |
4568 | 4671 |
4569 {"utcnow", (PyCFunction)datetime_utcnow, | 4672 {"utcnow", (PyCFunction)datetime_utcnow, |
4570 » METH_NOARGS | METH_CLASS, | 4673 » METH_VARARGS | METH_KEYWORDS | METH_CLASS, |
4571 » PyDoc_STR("Return a new datetime representing UTC day and time.")}, | 4674 » PyDoc_STR("[tz_aware] -> Return a new datetime "\ |
4675 "representing UTC day and time.")}, | |
4572 | 4676 |
4573 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp, | 4677 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp, |
4574 METH_VARARGS | METH_KEYWORDS | METH_CLASS, | 4678 METH_VARARGS | METH_KEYWORDS | METH_CLASS, |
4575 PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")}, | 4679 PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")}, |
4576 | 4680 |
4577 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp, | 4681 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp, |
4578 METH_VARARGS | METH_CLASS, | 4682 METH_VARARGS | METH_CLASS, |
4579 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp " | 4683 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp " |
4580 "(like time.time()).")}, | 4684 "(like time.time()).")}, |
4581 | 4685 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4709 | 4813 |
4710 /* C API. Clients get at this via PyDateTime_IMPORT, defined in | 4814 /* C API. Clients get at this via PyDateTime_IMPORT, defined in |
4711 * datetime.h. | 4815 * datetime.h. |
4712 */ | 4816 */ |
4713 static PyDateTime_CAPI CAPI = { | 4817 static PyDateTime_CAPI CAPI = { |
4714 &PyDateTime_DateType, | 4818 &PyDateTime_DateType, |
4715 &PyDateTime_DateTimeType, | 4819 &PyDateTime_DateTimeType, |
4716 &PyDateTime_TimeType, | 4820 &PyDateTime_TimeType, |
4717 &PyDateTime_DeltaType, | 4821 &PyDateTime_DeltaType, |
4718 &PyDateTime_TZInfoType, | 4822 &PyDateTime_TZInfoType, |
4823 &PyDateTime_UTCType, | |
4719 new_date_ex, | 4824 new_date_ex, |
4720 new_datetime_ex, | 4825 new_datetime_ex, |
4721 new_time_ex, | 4826 new_time_ex, |
4722 new_delta_ex, | 4827 new_delta_ex, |
4723 datetime_fromtimestamp, | 4828 datetime_fromtimestamp, |
4724 date_fromtimestamp | 4829 date_fromtimestamp |
4725 }; | 4830 }; |
4726 | 4831 |
4727 | 4832 |
4728 PyMODINIT_FUNC | 4833 PyMODINIT_FUNC |
(...skipping 11 matching lines...) Expand all Loading... | |
4740 if (PyType_Ready(&PyDateTime_DateType) < 0) | 4845 if (PyType_Ready(&PyDateTime_DateType) < 0) |
4741 return; | 4846 return; |
4742 if (PyType_Ready(&PyDateTime_DateTimeType) < 0) | 4847 if (PyType_Ready(&PyDateTime_DateTimeType) < 0) |
4743 return; | 4848 return; |
4744 if (PyType_Ready(&PyDateTime_DeltaType) < 0) | 4849 if (PyType_Ready(&PyDateTime_DeltaType) < 0) |
4745 return; | 4850 return; |
4746 if (PyType_Ready(&PyDateTime_TimeType) < 0) | 4851 if (PyType_Ready(&PyDateTime_TimeType) < 0) |
4747 return; | 4852 return; |
4748 if (PyType_Ready(&PyDateTime_TZInfoType) < 0) | 4853 if (PyType_Ready(&PyDateTime_TZInfoType) < 0) |
4749 return; | 4854 return; |
4855 if (PyType_Ready(&PyDateTime_UTCType) < 0) | |
4856 return; | |
4750 | 4857 |
4751 /* timedelta values */ | 4858 /* timedelta values */ |
4752 d = PyDateTime_DeltaType.tp_dict; | 4859 d = PyDateTime_DeltaType.tp_dict; |
4753 | 4860 |
4754 x = new_delta(0, 0, 1, 0); | 4861 x = new_delta(0, 0, 1, 0); |
4755 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) | 4862 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) |
4756 return; | 4863 return; |
4757 Py_DECREF(x); | 4864 Py_DECREF(x); |
4758 | 4865 |
4759 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0); | 4866 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4833 | 4940 |
4834 Py_INCREF(&PyDateTime_TimeType); | 4941 Py_INCREF(&PyDateTime_TimeType); |
4835 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType); | 4942 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType); |
4836 | 4943 |
4837 Py_INCREF(&PyDateTime_DeltaType); | 4944 Py_INCREF(&PyDateTime_DeltaType); |
4838 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType); | 4945 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType); |
4839 | 4946 |
4840 Py_INCREF(&PyDateTime_TZInfoType); | 4947 Py_INCREF(&PyDateTime_TZInfoType); |
4841 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType); | 4948 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType); |
4842 | 4949 |
4950 Py_INCREF(&PyDateTime_UTCType); | |
4951 PyModule_AddObject(m, "UTC", (PyObject *) &PyDateTime_UTCType); | |
4952 | |
4843 x = PyCObject_FromVoidPtrAndDesc(&CAPI, (void*) DATETIME_API_MAGIC, | 4953 x = PyCObject_FromVoidPtrAndDesc(&CAPI, (void*) DATETIME_API_MAGIC, |
4844 NULL); | 4954 NULL); |
4845 if (x == NULL) | 4955 if (x == NULL) |
4846 return; | 4956 return; |
4847 PyModule_AddObject(m, "datetime_CAPI", x); | 4957 PyModule_AddObject(m, "datetime_CAPI", x); |
4848 | 4958 |
4849 /* A 4-year cycle has an extra leap day over what we'd get from | 4959 /* A 4-year cycle has an extra leap day over what we'd get from |
4850 * pasting together 4 single years. | 4960 * pasting together 4 single years. |
4851 */ | 4961 */ |
4852 assert(DI4Y == 4 * 365 + 1); | 4962 assert(DI4Y == 4 * 365 + 1); |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5073 enough to say. | 5183 enough to say. |
5074 | 5184 |
5075 In any case, it's clear that the default fromutc() is strong enough to handle | 5185 In any case, it's clear that the default fromutc() is strong enough to handle |
5076 "almost all" time zones: so long as the standard offset is invariant, it | 5186 "almost all" time zones: so long as the standard offset is invariant, it |
5077 doesn't matter if daylight time transition points change from year to year, or | 5187 doesn't matter if daylight time transition points change from year to year, or |
5078 if daylight time is skipped in some years; it doesn't matter how large or | 5188 if daylight time is skipped in some years; it doesn't matter how large or |
5079 small dst() may get within its bounds; and it doesn't even matter if some | 5189 small dst() may get within its bounds; and it doesn't even matter if some |
5080 perverse time zone returns a negative dst()). So a breaking case must be | 5190 perverse time zone returns a negative dst()). So a breaking case must be |
5081 pretty bizarre, and a tzinfo subclass can override fromutc() if it is. | 5191 pretty bizarre, and a tzinfo subclass can override fromutc() if it is. |
5082 --------------------------------------------------------------------------- */ | 5192 --------------------------------------------------------------------------- */ |
OLD | NEW |