Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
73ca440e
Commit
73ca440e
authored
Jul 07, 2010
by
Alexander Belopolsky
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #5288: Eliminated round-trips between timdelta and int offsets
parent
6ef08a0e
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
398 additions
and
475 deletions
+398
-475
Modules/datetimemodule.c
Modules/datetimemodule.c
+398
-475
No files found.
Modules/datetimemodule.c
View file @
73ca440e
...
...
@@ -88,8 +88,11 @@
/* p is a pointer to a time or a datetime object; HASTZINFO(p) returns
* p->hastzinfo.
*/
#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo)
#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo)
#define GET_TIME_TZINFO(p) (HASTZINFO(p) ? \
((PyDateTime_Time *)(p))->tzinfo : Py_None)
#define GET_DT_TZINFO(p) (HASTZINFO(p) ? \
((PyDateTime_DateTime *)(p))->tzinfo : Py_None)
/* M is a char or int claiming to be a valid month. The macro is equivalent
* to the two-sided Python test
* 1 <= M <= 12
...
...
@@ -839,25 +842,6 @@ check_tzinfo_subclass(PyObject *p)
return
-
1
;
}
/* Return tzinfo.methname(tzinfoarg), without any checking of results.
* If tzinfo is None, returns None.
*/
static
PyObject
*
call_tzinfo_method
(
PyObject
*
tzinfo
,
char
*
methname
,
PyObject
*
tzinfoarg
)
{
PyObject
*
result
;
assert
(
tzinfo
&&
methname
&&
tzinfoarg
);
assert
(
check_tzinfo_subclass
(
tzinfo
)
>=
0
);
if
(
tzinfo
==
Py_None
)
{
result
=
Py_None
;
Py_INCREF
(
result
);
}
else
result
=
PyObject_CallMethod
(
tzinfo
,
methname
,
"O"
,
tzinfoarg
);
return
result
;
}
/* If self has a tzinfo member, return a BORROWED reference to it. Else
* return NULL, which is NOT AN ERROR. There are no error returns here,
* and the caller must not decref the result.
...
...
@@ -875,69 +859,53 @@ get_tzinfo_member(PyObject *self)
return
tzinfo
;
}
/* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
* result. tzinfo must be an instance of the tzinfo class. If the method
* returns None, this returns 0 and sets *none to 1. If the method doesn't
* return None or timedelta, TypeError is raised and this returns -1. If it
* returnsa timedelta and the value is out of range or isn't a whole number
* of minutes, ValueError is raised and this returns -1.
* Else *none is set to 0 and the integer method result is returned.
/* Call getattr(tzinfo, name)(tzinfoarg), and check the result. tzinfo must
* be an instance of the tzinfo class. If the method returns None, this
* returns None. If the method doesn't return None or timedelta, TypeError is
* raised and this returns NULL. If it returns a timedelta and the value is
* out of range or isn't a whole number of minutes, ValueError is raised and
* this returns NULL. Else result is returned.
*/
static
int
call_utc_tzinfo_method
(
PyObject
*
tzinfo
,
char
*
name
,
PyObject
*
tzinfoarg
,
int
*
none
)
static
PyObject
*
call_tzinfo_method
(
PyObject
*
tzinfo
,
char
*
name
,
PyObject
*
tzinfoarg
)
{
PyObject
*
u
;
int
result
=
-
1
;
PyObject
*
offset
;
assert
(
tzinfo
!=
NULL
);
assert
(
PyTZInfo_Check
(
tzinfo
));
assert
(
PyTZInfo_Check
(
tzinfo
)
||
tzinfo
==
Py_None
);
assert
(
tzinfoarg
!=
NULL
);
*
none
=
0
;
u
=
call_tzinfo_method
(
tzinfo
,
name
,
tzinfoarg
);
if
(
u
==
NULL
)
return
-
1
;
else
if
(
u
==
Py_None
)
{
result
=
0
;
*
none
=
1
;
}
else
if
(
PyDelta_Check
(
u
))
{
const
int
days
=
GET_TD_DAYS
(
u
);
if
(
days
<
-
1
||
days
>
0
)
result
=
24
*
60
;
/* trigger ValueError below */
else
{
/* next line can't overflow because we know days
* is -1 or 0 now
*/
int
ss
=
days
*
24
*
3600
+
GET_TD_SECONDS
(
u
);
result
=
divmod
(
ss
,
60
,
&
ss
);
if
(
ss
||
GET_TD_MICROSECONDS
(
u
))
{
PyErr_Format
(
PyExc_ValueError
,
"tzinfo.%s() must return a "
"whole number of minutes"
,
name
);
result
=
-
1
;
}
if
(
tzinfo
==
Py_None
)
Py_RETURN_NONE
;
offset
=
PyObject_CallMethod
(
tzinfo
,
name
,
"O"
,
tzinfoarg
);
if
(
offset
==
Py_None
||
offset
==
NULL
)
return
offset
;
if
(
PyDelta_Check
(
offset
))
{
if
(
GET_TD_MICROSECONDS
(
offset
)
!=
0
||
GET_TD_SECONDS
(
offset
)
%
60
!=
0
)
{
Py_DECREF
(
offset
);
PyErr_Format
(
PyExc_ValueError
,
"offset must be a timedelta"
" representing a whole number of minutes"
);
return
NULL
;
}
if
((
GET_TD_DAYS
(
offset
)
==
-
1
&&
GET_TD_SECONDS
(
offset
)
==
0
)
||
GET_TD_DAYS
(
offset
)
<
-
1
||
GET_TD_DAYS
(
offset
)
>=
1
)
{
Py_DECREF
(
offset
);
PyErr_Format
(
PyExc_ValueError
,
"offset must be a timedelta"
" strictly between -timedelta(hours=24) and"
" timedelta(hours=24)."
);
return
NULL
;
}
}
else
{
Py_DECREF
(
offset
);
PyErr_Format
(
PyExc_TypeError
,
"tzinfo.%s() must return None or "
"timedelta, not '%s'"
,
name
,
Py_TYPE
(
u
)
->
tp_name
);
"timedelta, not '%.200s'"
,
name
,
Py_TYPE
(
offset
)
->
tp_name
);
return
NULL
;
}
Py_DECREF
(
u
);
if
(
result
<
-
1439
||
result
>
1439
)
{
PyErr_Format
(
PyExc_ValueError
,
"tzinfo.%s() returned %d; must be in "
"-1439 .. 1439"
,
name
,
result
);
result
=
-
1
;
}
return
result
;
return
offset
;
}
/* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the
...
...
@@ -948,37 +916,10 @@ call_utc_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg,
* # of minutes), ValueError is raised and this returns -1. Else *none is
* set to 0 and the offset is returned (as int # of minutes east of UTC).
*/
static
int
call_utcoffset
(
PyObject
*
tzinfo
,
PyObject
*
tzinfoarg
,
int
*
none
)
{
return
call_utc_tzinfo_method
(
tzinfo
,
"utcoffset"
,
tzinfoarg
,
none
);
}
/* Call tzinfo.name(tzinfoarg), and return the offset as a timedelta or None.
*/
static
PyObject
*
offset_as_timedelta
(
PyObject
*
tzinfo
,
char
*
name
,
PyObject
*
tzinfoarg
)
{
PyObject
*
result
;
assert
(
tzinfo
&&
name
&&
tzinfoarg
);
if
(
tzinfo
==
Py_None
)
{
result
=
Py_None
;
Py_INCREF
(
result
);
}
else
{
int
none
;
int
offset
=
call_utc_tzinfo_method
(
tzinfo
,
name
,
tzinfoarg
,
&
none
);
if
(
offset
<
0
&&
PyErr_Occurred
())
return
NULL
;
if
(
none
)
{
result
=
Py_None
;
Py_INCREF
(
result
);
}
else
result
=
new_delta
(
0
,
offset
*
60
,
0
,
1
);
}
return
result
;
call_utcoffset
(
PyObject
*
tzinfo
,
PyObject
*
tzinfoarg
)
{
return
call_tzinfo_method
(
tzinfo
,
"utcoffset"
,
tzinfoarg
);
}
/* Call tzinfo.dst(tzinfoarg), and extract an integer from the
...
...
@@ -989,10 +930,10 @@ offset_as_timedelta(PyObject *tzinfo, char *name, PyObject *tzinfoarg) {
* ValueError is raised and this returns -1. Else *none is set to 0 and
* the offset is returned (as an int # of minutes east of UTC).
*/
static
int
call_dst
(
PyObject
*
tzinfo
,
PyObject
*
tzinfoarg
,
int
*
none
)
static
PyObject
*
call_dst
(
PyObject
*
tzinfo
,
PyObject
*
tzinfoarg
)
{
return
call_
utc_tzinfo_method
(
tzinfo
,
"dst"
,
tzinfoarg
,
none
);
return
call_
tzinfo_method
(
tzinfo
,
"dst"
,
tzinfoarg
);
}
/* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be
...
...
@@ -1010,102 +951,23 @@ call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
assert
(
check_tzinfo_subclass
(
tzinfo
)
>=
0
);
assert
(
tzinfoarg
!=
NULL
);
if
(
tzinfo
==
Py_None
)
{
result
=
Py_None
;
Py_INCREF
(
result
);
}
else
result
=
PyObject_CallMethod
(
tzinfo
,
"tzname"
,
"O"
,
tzinfoarg
);
if
(
result
!=
NULL
&&
result
!=
Py_None
)
{
if
(
!
PyUnicode_Check
(
result
))
{
PyErr_Format
(
PyExc_TypeError
,
"tzinfo.tzname() must "
"return None or a string, not '%s'"
,
Py_TYPE
(
result
)
->
tp_name
);
Py_DECREF
(
result
);
result
=
NULL
;
}
}
return
result
;
}
if
(
tzinfo
==
Py_None
)
Py_RETURN_NONE
;
typedef
enum
{
/* an exception has been set; the caller should pass it on */
OFFSET_ERROR
,
/* type isn't date, datetime, or time subclass */
OFFSET_UNKNOWN
,
/* date,
* datetime with !hastzinfo
* datetime with None tzinfo,
* datetime where utcoffset() returns None
* time with !hastzinfo
* time with None tzinfo,
* time where utcoffset() returns None
*/
OFFSET_NAIVE
,
/* time or datetime where utcoffset() doesn't return None */
OFFSET_AWARE
}
naivety
;
/* Classify an object as to whether it's naive or offset-aware. See
* the "naivety" typedef for details. If the type is aware, *offset is set
* to minutes east of UTC (as returned by the tzinfo.utcoffset() method).
* If the type is offset-naive (or unknown, or error), *offset is set to 0.
* tzinfoarg is the argument to pass to the tzinfo.utcoffset() method.
*/
static
naivety
classify_utcoffset
(
PyObject
*
op
,
PyObject
*
tzinfoarg
,
int
*
offset
)
{
int
none
;
PyObject
*
tzinfo
;
result
=
PyObject_CallMethod
(
tzinfo
,
"tzname"
,
"O"
,
tzinfoarg
);
assert
(
tzinfoarg
!=
NULL
);
*
offset
=
0
;
tzinfo
=
get_tzinfo_member
(
op
);
/* NULL means no tzinfo, not error */
if
(
tzinfo
==
Py_None
)
return
OFFSET_NAIVE
;
if
(
tzinfo
==
NULL
)
{
/* note that a datetime passes the PyDate_Check test */
return
(
PyTime_Check
(
op
)
||
PyDate_Check
(
op
))
?
OFFSET_NAIVE
:
OFFSET_UNKNOWN
;
}
*
offset
=
call_utcoffset
(
tzinfo
,
tzinfoarg
,
&
none
);
if
(
*
offset
==
-
1
&&
PyErr_Occurred
())
return
OFFSET_ERROR
;
return
none
?
OFFSET_NAIVE
:
OFFSET_AWARE
;
}
/* Classify two objects as to whether they're naive or offset-aware.
* This isn't quite the same as calling classify_utcoffset() twice: for
* binary operations (comparison and subtraction), we generally want to
* ignore the tzinfo members if they're identical. This is by design,
* so that results match "naive" expectations when mixing objects from a
* single timezone. So in that case, this sets both offsets to 0 and
* both naiveties to OFFSET_NAIVE.
* The function returns 0 if everything's OK, and -1 on error.
*/
static
int
classify_two_utcoffsets
(
PyObject
*
o1
,
int
*
offset1
,
naivety
*
n1
,
PyObject
*
tzinfoarg1
,
PyObject
*
o2
,
int
*
offset2
,
naivety
*
n2
,
PyObject
*
tzinfoarg2
)
{
if
(
get_tzinfo_member
(
o1
)
==
get_tzinfo_member
(
o2
))
{
*
offset1
=
*
offset2
=
0
;
*
n1
=
*
n2
=
OFFSET_NAIVE
;
}
else
{
*
n1
=
classify_utcoffset
(
o1
,
tzinfoarg1
,
offset1
);
if
(
*
n1
==
OFFSET_ERROR
)
return
-
1
;
*
n2
=
classify_utcoffset
(
o2
,
tzinfoarg2
,
offset2
);
if
(
*
n2
==
OFFSET_ERROR
)
return
-
1
;
if
(
result
==
NULL
||
result
==
Py_None
)
return
result
;
if
(
!
PyUnicode_Check
(
result
))
{
PyErr_Format
(
PyExc_TypeError
,
"tzinfo.tzname() must "
"return None or a string, not '%s'"
,
Py_TYPE
(
result
)
->
tp_name
);
Py_DECREF
(
result
);
result
=
NULL
;
}
return
0
;
return
result
;
}
/* repr is like "someclass(arg1, arg2)". If tzinfo isn't None,
...
...
@@ -1157,6 +1019,8 @@ format_ctime(PyDateTime_Date *date, int hours, int minutes, int seconds)
GET_YEAR
(
date
));
}
static
PyObject
*
delta_negative
(
PyDateTime_Delta
*
self
);
/* Add an hours & minutes UTC offset string to buf. buf has no more than
* buflen bytes remaining. The UTC offset is gotten by calling
* tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into
...
...
@@ -1171,28 +1035,41 @@ static int
format_utcoffset
(
char
*
buf
,
size_t
buflen
,
const
char
*
sep
,
PyObject
*
tzinfo
,
PyObject
*
tzinfoarg
)
{
int
offset
;
int
hours
;
int
minutes
;
PyObject
*
offset
;
int
hours
,
minutes
,
seconds
;
char
sign
;
int
none
;
assert
(
buflen
>=
1
);
offset
=
call_utcoffset
(
tzinfo
,
tzinfoarg
,
&
none
);
if
(
offset
==
-
1
&&
PyErr_Occurred
()
)
offset
=
call_utcoffset
(
tzinfo
,
tzinfoarg
);
if
(
offset
==
NULL
)
return
-
1
;
if
(
none
)
{
if
(
offset
==
Py_None
)
{
Py_DECREF
(
offset
);
*
buf
=
'\0'
;
return
0
;
}
sign
=
'+'
;
if
(
offset
<
0
)
{
/* Offset is normalized, so it is negative if days < 0 */
if
(
GET_TD_DAYS
(
offset
)
<
0
)
{
PyObject
*
temp
=
offset
;
sign
=
'-'
;
offset
=
-
offset
;
offset
=
delta_negative
((
PyDateTime_Delta
*
)
offset
);
Py_DECREF
(
temp
);
if
(
offset
==
NULL
)
return
-
1
;
}
else
{
sign
=
'+'
;
}
hours
=
divmod
(
offset
,
60
,
&
minutes
);
/* Offset is not negative here. */
seconds
=
GET_TD_SECONDS
(
offset
);
Py_DECREF
(
offset
);
minutes
=
divmod
(
seconds
,
60
,
&
seconds
);
hours
=
divmod
(
minutes
,
60
,
&
minutes
);
assert
(
seconds
==
0
);
/* XXX ignore sub-minute data, curently not allowed. */
PyOS_snprintf
(
buf
,
buflen
,
"%c%02d%s%02d"
,
sign
,
hours
,
sep
,
minutes
);
return
0
;
}
...
...
@@ -1434,7 +1311,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
format
=
PyUnicode_FromString
(
PyBytes_AS_STRING
(
newfmt
));
if
(
format
!=
NULL
)
{
result
=
PyObject_CallMethod
(
time
,
"strftime"
,
"OO"
,
format
,
timetuple
);
format
,
timetuple
,
NULL
);
Py_DECREF
(
format
);
}
Py_DECREF
(
time
);
...
...
@@ -1937,17 +1814,24 @@ delta_subtract(PyObject *left, PyObject *right)
return
result
;
}
static
int
delta_cmp
(
PyObject
*
self
,
PyObject
*
other
)
{
int
diff
=
GET_TD_DAYS
(
self
)
-
GET_TD_DAYS
(
other
);
if
(
diff
==
0
)
{
diff
=
GET_TD_SECONDS
(
self
)
-
GET_TD_SECONDS
(
other
);
if
(
diff
==
0
)
diff
=
GET_TD_MICROSECONDS
(
self
)
-
GET_TD_MICROSECONDS
(
other
);
}
return
diff
;
}
static
PyObject
*
delta_richcompare
(
PyObject
*
self
,
PyObject
*
other
,
int
op
)
{
if
(
PyDelta_Check
(
other
))
{
int
diff
=
GET_TD_DAYS
(
self
)
-
GET_TD_DAYS
(
other
);
if
(
diff
==
0
)
{
diff
=
GET_TD_SECONDS
(
self
)
-
GET_TD_SECONDS
(
other
);
if
(
diff
==
0
)
diff
=
GET_TD_MICROSECONDS
(
self
)
-
GET_TD_MICROSECONDS
(
other
);
}
int
diff
=
delta_cmp
(
self
,
other
);
return
diff_to_bool
(
diff
,
op
);
}
else
{
...
...
@@ -3119,76 +3003,73 @@ tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
return
tzinfo_nogo
(
"dst"
);
}
static
PyObject
*
add_datetime_timedelta
(
PyDateTime_DateTime
*
date
,
PyDateTime_Delta
*
delta
,
int
factor
);
static
PyObject
*
datetime_utcoffset
(
PyObject
*
self
,
PyObject
*
);
static
PyObject
*
datetime_dst
(
PyObject
*
self
,
PyObject
*
);
static
PyObject
*
tzinfo_fromutc
(
PyDateTime_TZInfo
*
self
,
Py
DateTime_DateTime
*
dt
)
tzinfo_fromutc
(
PyDateTime_TZInfo
*
self
,
Py
Object
*
dt
)
{
int
y
,
m
,
d
,
hh
,
mm
,
ss
,
us
;
PyObject
*
result
;
int
off
,
dst
;
int
none
;
int
delta
;
PyObject
*
result
=
NULL
;
PyObject
*
off
=
NULL
,
*
dst
=
NULL
;
PyDateTime_Delta
*
delta
=
NULL
;
if
(
!
PyDateTime_Check
(
dt
))
{
if
(
!
PyDateTime_Check
(
dt
))
{
PyErr_SetString
(
PyExc_TypeError
,
"fromutc: argument must be a datetime"
);
return
NULL
;
}
if
(
!
HASTZINFO
(
dt
)
||
dt
->
tzinfo
!=
(
PyObject
*
)
self
)
{
if
(
GET_DT_TZINFO
(
dt
)
!=
(
PyObject
*
)
self
)
{
PyErr_SetString
(
PyExc_ValueError
,
"fromutc: dt.tzinfo "
"is not self"
);
return
NULL
;
}
off
=
call_utcoffset
(
dt
->
tzinfo
,
(
PyObject
*
)
dt
,
&
none
);
if
(
off
==
-
1
&&
PyErr_Occurred
()
)
off
=
datetime_utcoffset
(
dt
,
NULL
);
if
(
off
==
NULL
)
return
NULL
;
if
(
n
one
)
{
if
(
off
==
Py_N
one
)
{
PyErr_SetString
(
PyExc_ValueError
,
"fromutc: non-None "
"utcoffset() result required"
);
return
NULL
;
goto
Fail
;
}
dst
=
call_dst
(
dt
->
tzinfo
,
(
PyObject
*
)
dt
,
&
none
);
if
(
dst
==
-
1
&&
PyErr_Occurred
()
)
return
NULL
;
if
(
n
one
)
{
dst
=
datetime_dst
(
dt
,
NULL
);
if
(
dst
==
NULL
)
goto
Fail
;
if
(
dst
==
Py_N
one
)
{
PyErr_SetString
(
PyExc_ValueError
,
"fromutc: non-None "
"dst() result required"
);
return
NULL
;
goto
Fail
;
}
y
=
GET_YEAR
(
dt
);
m
=
GET_MONTH
(
dt
);
d
=
GET_DAY
(
dt
);
hh
=
DATE_GET_HOUR
(
dt
);
mm
=
DATE_GET_MINUTE
(
dt
);
ss
=
DATE_GET_SECOND
(
dt
);
us
=
DATE_GET_MICROSECOND
(
dt
);
delta
=
off
-
dst
;
mm
+=
delta
;
if
((
mm
<
0
||
mm
>=
60
)
&&
normalize_datetime
(
&
y
,
&
m
,
&
d
,
&
hh
,
&
mm
,
&
ss
,
&
us
)
<
0
)
return
NULL
;
result
=
new_datetime
(
y
,
m
,
d
,
hh
,
mm
,
ss
,
us
,
dt
->
tzinfo
);
delta
=
(
PyDateTime_Delta
*
)
delta_subtract
(
off
,
dst
);
if
(
delta
==
NULL
)
goto
Fail
;
result
=
add_datetime_timedelta
((
PyDateTime_DateTime
*
)
dt
,
delta
,
1
);
if
(
result
==
NULL
)
return
result
;
dst
=
call_dst
(
dt
->
tzinfo
,
result
,
&
none
);
if
(
dst
==
-
1
&&
PyErr_Occurred
())
goto
Fail
;
if
(
none
)
goto
Inconsistent
;
if
(
dst
==
0
)
return
result
;
mm
+=
dst
;
if
((
mm
<
0
||
mm
>=
60
)
&&
normalize_datetime
(
&
y
,
&
m
,
&
d
,
&
hh
,
&
mm
,
&
ss
,
&
us
)
<
0
)
Py_DECREF
(
dst
)
;
dst
=
call_dst
(
GET_DT_TZINFO
(
dt
),
result
);
if
(
dst
==
NULL
)
goto
Fail
;
Py_DECREF
(
result
);
result
=
new_datetime
(
y
,
m
,
d
,
hh
,
mm
,
ss
,
us
,
dt
->
tzinfo
);
if
(
dst
==
Py_None
)
goto
Inconsistent
;
if
(
delta_bool
(
delta
)
!=
0
)
{
PyObject
*
temp
=
result
;
result
=
add_datetime_timedelta
((
PyDateTime_DateTime
*
)
result
,
(
PyDateTime_Delta
*
)
dst
,
1
);
Py_DECREF
(
temp
);
if
(
result
==
NULL
)
goto
Fail
;
}
Py_DECREF
(
delta
);
Py_DECREF
(
dst
);
Py_DECREF
(
off
);
return
result
;
Inconsistent:
...
...
@@ -3197,7 +3078,10 @@ Inconsistent:
/* fall thru to failure */
Fail:
Py_DECREF
(
result
);
Py_XDECREF
(
off
);
Py_XDECREF
(
dst
);
Py_XDECREF
(
delta
);
Py_XDECREF
(
result
);
return
NULL
;
}
...
...
@@ -3463,19 +3347,15 @@ timezone_dst(PyObject *self, PyObject *dt)
Py_RETURN_NONE
;
}
static
PyObject
*
add_datetime_timedelta
(
PyDateTime_DateTime
*
date
,
PyDateTime_Delta
*
delta
,
int
factor
);
static
PyObject
*
timezone_fromutc
(
PyDateTime_TimeZone
*
self
,
PyDateTime_DateTime
*
dt
)
{
if
(
!
PyDateTime_Check
(
dt
))
{
if
(
!
PyDateTime_Check
(
dt
))
{
PyErr_SetString
(
PyExc_TypeError
,
"fromutc: argument must be a datetime"
);
return
NULL
;
}
if
(
!
HASTZINFO
(
dt
)
||
dt
->
tzinfo
!=
(
PyObject
*
)
self
)
{
if
(
!
HASTZINFO
(
dt
)
||
dt
->
tzinfo
!=
(
PyObject
*
)
self
)
{
PyErr_SetString
(
PyExc_ValueError
,
"fromutc: dt.tzinfo "
"is not self"
);
return
NULL
;
...
...
@@ -3689,21 +3569,18 @@ time_dealloc(PyDateTime_Time *self)
/* These are all METH_NOARGS, so don't need to check the arglist. */
static
PyObject
*
time_utcoffset
(
PyDateTime_Time
*
self
,
PyObject
*
unused
)
{
return
offset_as_timedelta
(
HASTZINFO
(
self
)
?
self
->
tzinfo
:
Py_None
,
"utcoffset"
,
Py_None
);
time_utcoffset
(
PyObject
*
self
,
PyObject
*
unused
)
{
return
call_utcoffset
(
GET_TIME_TZINFO
(
self
),
Py_None
);
}
static
PyObject
*
time_dst
(
PyDateTime_Time
*
self
,
PyObject
*
unused
)
{
return
offset_as_timedelta
(
HASTZINFO
(
self
)
?
self
->
tzinfo
:
Py_None
,
"dst"
,
Py_None
);
time_dst
(
PyObject
*
self
,
PyObject
*
unused
)
{
return
call_dst
(
GET_TIME_TZINFO
(
self
),
Py_None
);
}
static
PyObject
*
time_tzname
(
PyDateTime_Time
*
self
,
PyObject
*
unused
)
{
return
call_tzname
(
HASTZINFO
(
self
)
?
self
->
tzinfo
:
Py_None
,
Py_None
);
return
call_tzname
(
GET_TIME_TZINFO
(
self
),
Py_None
);
}
/*
...
...
@@ -3758,7 +3635,7 @@ time_isoformat(PyDateTime_Time *self, PyObject *unused)
TIME_GET_MINUTE
(
self
),
TIME_GET_SECOND
(
self
));
if
(
result
==
NULL
||
!
HASTZINFO
(
self
)
||
self
->
tzinfo
==
Py_None
)
if
(
result
==
NULL
||
!
HASTZINFO
(
self
)
||
self
->
tzinfo
==
Py_None
)
return
result
;
/* We need to append the UTC offset. */
...
...
@@ -3809,98 +3686,108 @@ time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
static
PyObject
*
time_richcompare
(
PyObject
*
self
,
PyObject
*
other
,
int
op
)
{
PyObject
*
result
=
NULL
;
PyObject
*
offset1
,
*
offset2
;
int
diff
;
naivety
n1
,
n2
;
int
offset1
,
offset2
;
if
(
!
PyTime_Check
(
other
))
{
Py_INCREF
(
Py_NotImplemented
);
return
Py_NotImplemented
;
}
if
(
classify_two_utcoffsets
(
self
,
&
offset1
,
&
n1
,
Py_None
,
other
,
&
offset2
,
&
n2
,
Py_None
)
<
0
)
if
(
GET_TIME_TZINFO
(
self
)
==
GET_TIME_TZINFO
(
other
))
{
diff
=
memcmp
(((
PyDateTime_Time
*
)
self
)
->
data
,
((
PyDateTime_Time
*
)
other
)
->
data
,
_PyDateTime_TIME_DATASIZE
);
return
diff_to_bool
(
diff
,
op
);
}
offset1
=
time_utcoffset
(
self
,
NULL
);
if
(
offset1
==
NULL
)
return
NULL
;
assert
(
n1
!=
OFFSET_UNKNOWN
&&
n2
!=
OFFSET_UNKNOWN
);
offset2
=
time_utcoffset
(
other
,
NULL
);
if
(
offset2
==
NULL
)
goto
done
;
/* If they're both naive, or both aware and have the same offsets,
* we get off cheap. Note that if they're both naive, offset1 ==
* offset2 ==
0
at this point.
* offset2 ==
Py_None
at this point.
*/
if
(
n1
==
n2
&&
offset1
==
offset2
)
{
if
((
offset1
==
offset2
)
||
(
PyDelta_Check
(
offset1
)
&&
PyDelta_Check
(
offset2
)
&&
delta_cmp
(
offset1
,
offset2
)
==
0
))
{
diff
=
memcmp
(((
PyDateTime_Time
*
)
self
)
->
data
,
((
PyDateTime_Time
*
)
other
)
->
data
,
_PyDateTime_TIME_DATASIZE
);
return
diff_to_bool
(
diff
,
op
);
}
if
(
n1
==
OFFSET_AWARE
&&
n2
==
OFFSET_AWARE
)
{
assert
(
offset1
!=
offset2
);
/* else last "if" handled it */
/* Convert everything except microseconds to seconds. These
* can't overflow (no more than the # of seconds in 2 days).
*/
offset1
=
TIME_GET_HOUR
(
self
)
*
3600
+
(
TIME_GET_MINUTE
(
self
)
-
offset1
)
*
60
+
TIME_GET_SECOND
(
self
);
offset2
=
TIME_GET_HOUR
(
other
)
*
3600
+
(
TIME_GET_MINUTE
(
other
)
-
offset2
)
*
60
+
TIME_GET_SECOND
(
other
);
diff
=
offset1
-
offset2
;
result
=
diff_to_bool
(
diff
,
op
);
}
/* The hard case: both aware with different UTC offsets */
else
if
(
offset1
!=
Py_None
&&
offset2
!=
Py_None
)
{
int
offsecs1
,
offsecs2
;
assert
(
offset1
!=
offset2
);
/* else last "if" handled it */
offsecs1
=
TIME_GET_HOUR
(
self
)
*
3600
+
TIME_GET_MINUTE
(
self
)
*
60
+
TIME_GET_SECOND
(
self
)
-
GET_TD_DAYS
(
offset1
)
*
86400
-
GET_TD_SECONDS
(
offset1
);
offsecs2
=
TIME_GET_HOUR
(
other
)
*
3600
+
TIME_GET_MINUTE
(
other
)
*
60
+
TIME_GET_SECOND
(
other
)
-
GET_TD_DAYS
(
offset2
)
*
86400
-
GET_TD_SECONDS
(
offset2
);
diff
=
offsecs1
-
offsecs2
;
if
(
diff
==
0
)
diff
=
TIME_GET_MICROSECOND
(
self
)
-
TIME_GET_MICROSECOND
(
other
);
re
turn
diff_to_bool
(
diff
,
op
);
re
sult
=
diff_to_bool
(
diff
,
op
);
}
assert
(
n1
!=
n2
);
PyErr_SetString
(
PyExc_TypeError
,
"can't compare offset-naive and "
"offset-aware times"
);
return
NULL
;
else
{
PyErr_SetString
(
PyExc_TypeError
,
"can't compare offset-naive and "
"offset-aware times"
);
}
done:
Py_DECREF
(
offset1
);
Py_XDECREF
(
offset2
);
return
result
;
}
static
long
time_hash
(
PyDateTime_Time
*
self
)
{
if
(
self
->
hashcode
==
-
1
)
{
naivety
n
;
int
offset
;
PyObject
*
temp
;
PyObject
*
offset
;
n
=
classify_utcoffset
((
PyObject
*
)
self
,
Py_None
,
&
offset
);
assert
(
n
!=
OFFSET_UNKNOWN
);
if
(
n
==
OFFSET_ERROR
)
offset
=
time_utcoffset
((
PyObject
*
)
self
,
NULL
);
if
(
offset
==
NULL
)
return
-
1
;
/* Reduce this to a hash of another object. */
if
(
offset
==
0
)
{
if
(
offset
==
Py_None
)
self
->
hashcode
=
generic_hash
(
(
unsigned
char
*
)
self
->
data
,
_PyDateTime_TIME_DATASIZE
);
return
self
->
hashcode
;
}
else
{
int
hour
;
int
minute
;
assert
(
n
==
OFFSET_AWARE
);
PyObject
*
temp1
,
*
temp2
;
int
seconds
,
microseconds
;
assert
(
HASTZINFO
(
self
));
hour
=
divmod
(
TIME_GET_HOUR
(
self
)
*
60
+
TIME_GET_MINUTE
(
self
)
-
offset
,
60
,
&
minute
);
if
(
0
<=
hour
&&
hour
<
24
)
temp
=
new_time
(
hour
,
minute
,
TIME_GET_SECOND
(
self
),
TIME_GET_MICROSECOND
(
self
),
Py_None
);
else
temp
=
Py_BuildValue
(
"iiii"
,
hour
,
minute
,
TIME_GET_SECOND
(
self
),
TIME_GET_MICROSECOND
(
self
));
}
if
(
temp
!=
NULL
)
{
self
->
hashcode
=
PyObject_Hash
(
temp
);
Py_DECREF
(
temp
);
seconds
=
TIME_GET_HOUR
(
self
)
*
3600
+
TIME_GET_MINUTE
(
self
)
*
60
+
TIME_GET_SECOND
(
self
);
microseconds
=
TIME_GET_MICROSECOND
(
self
);
temp1
=
new_delta
(
0
,
seconds
,
microseconds
,
1
);
if
(
temp1
==
NULL
)
{
Py_DECREF
(
offset
);
return
-
1
;
}
temp2
=
delta_subtract
(
temp1
,
offset
);
Py_DECREF
(
temp1
);
if
(
temp2
==
NULL
)
{
Py_DECREF
(
offset
);
return
-
1
;
}
self
->
hashcode
=
PyObject_Hash
(
temp2
);
Py_DECREF
(
temp2
);
}
Py_DECREF
(
offset
);
}
return
self
->
hashcode
;
}
...
...
@@ -3929,10 +3816,10 @@ time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
}
static
int
time_bool
(
Py
DateTime_Time
*
self
)
time_bool
(
Py
Object
*
self
)
{
int
offset
;
int
none
;
PyObject
*
offset
,
*
tzinfo
;
int
offsecs
=
0
;
if
(
TIME_GET_SECOND
(
self
)
||
TIME_GET_MICROSECOND
(
self
))
{
/* Since utcoffset is in whole minutes, nothing can
...
...
@@ -3940,13 +3827,15 @@ time_bool(PyDateTime_Time *self)
*/
return
1
;
}
offset
=
0
;
if
(
HASTZINFO
(
self
)
&&
self
->
tzinfo
!=
Py_None
)
{
offset
=
call_utcoffset
(
self
->
tzinfo
,
Py_None
,
&
n
one
);
if
(
offset
==
-
1
&&
PyErr_Occurred
()
)
tzinfo
=
GET_TIME_TZINFO
(
self
)
;
if
(
tzinfo
!=
Py_None
)
{
offset
=
call_utcoffset
(
tzinfo
,
Py_N
one
);
if
(
offset
==
NULL
)
return
-
1
;
offsecs
=
GET_TD_DAYS
(
offset
)
*
86400
+
GET_TD_SECONDS
(
offset
);
Py_DECREF
(
offset
);
}
return
(
TIME_GET_MINUTE
(
self
)
-
offset
+
TIME_GET_HOUR
(
self
)
*
6
0
)
!=
0
;
return
(
TIME_GET_MINUTE
(
self
)
*
60
-
offsecs
+
TIME_GET_HOUR
(
self
)
*
360
0
)
!=
0
;
}
/* Pickle support, a simple use of __reduce__. */
...
...
@@ -4455,21 +4344,18 @@ datetime_dealloc(PyDateTime_DateTime *self)
/* These are all METH_NOARGS, so don't need to check the arglist. */
static
PyObject
*
datetime_utcoffset
(
PyDateTime_DateTime
*
self
,
PyObject
*
unused
)
{
return
offset_as_timedelta
(
HASTZINFO
(
self
)
?
self
->
tzinfo
:
Py_None
,
"utcoffset"
,
(
PyObject
*
)
self
);
datetime_utcoffset
(
PyObject
*
self
,
PyObject
*
unused
)
{
return
call_utcoffset
(
GET_DT_TZINFO
(
self
),
self
);
}
static
PyObject
*
datetime_dst
(
PyDateTime_DateTime
*
self
,
PyObject
*
unused
)
{
return
offset_as_timedelta
(
HASTZINFO
(
self
)
?
self
->
tzinfo
:
Py_None
,
"dst"
,
(
PyObject
*
)
self
);
datetime_dst
(
PyObject
*
self
,
PyObject
*
unused
)
{
return
call_dst
(
GET_DT_TZINFO
(
self
),
self
);
}
static
PyObject
*
datetime_tzname
(
PyDateTime_DateTime
*
self
,
PyObject
*
unused
)
{
return
call_tzname
(
HASTZINFO
(
self
)
?
self
->
tzinfo
:
Py_None
,
(
PyObject
*
)
self
);
datetime_tzname
(
PyObject
*
self
,
PyObject
*
unused
)
{
return
call_tzname
(
GET_DT_TZINFO
(
self
),
self
);
}
/*
...
...
@@ -4536,21 +4422,43 @@ datetime_subtract(PyObject *left, PyObject *right)
/* datetime - ??? */
if
(
PyDateTime_Check
(
right
))
{
/* datetime - datetime */
naivety
n1
,
n2
;
int
offset1
,
offset2
;
PyObject
*
offset1
,
*
offset2
,
*
offdiff
=
NULL
;
int
delta_d
,
delta_s
,
delta_us
;
if
(
classify_two_utcoffsets
(
left
,
&
offset1
,
&
n1
,
left
,
right
,
&
offset2
,
&
n2
,
right
)
<
0
)
return
NULL
;
assert
(
n1
!=
OFFSET_UNKNOWN
&&
n2
!=
OFFSET_UNKNOWN
);
if
(
n1
!=
n2
)
{
PyErr_SetString
(
PyExc_TypeError
,
"can't subtract offset-naive and "
"offset-aware datetimes"
);
return
NULL
;
if
(
GET_DT_TZINFO
(
left
)
==
GET_DT_TZINFO
(
right
))
{
offset2
=
offset1
=
Py_None
;
Py_INCREF
(
offset1
);
Py_INCREF
(
offset2
);
}
else
{
offset1
=
datetime_utcoffset
(
left
,
NULL
);
if
(
offset1
==
NULL
)
return
NULL
;
offset2
=
datetime_utcoffset
(
right
,
NULL
);
if
(
offset2
==
NULL
)
{
Py_DECREF
(
offset1
);
return
NULL
;
}
if
((
offset1
!=
Py_None
)
!=
(
offset2
!=
Py_None
))
{
PyErr_SetString
(
PyExc_TypeError
,
"can't subtract offset-naive and "
"offset-aware datetimes"
);
Py_DECREF
(
offset1
);
Py_DECREF
(
offset2
);
return
NULL
;
}
}
if
((
offset1
!=
offset2
)
&&
delta_cmp
(
offset1
,
offset2
)
!=
0
)
{
offdiff
=
delta_subtract
(
offset1
,
offset2
);
if
(
offdiff
==
NULL
)
{
Py_DECREF
(
offset1
);
Py_DECREF
(
offset2
);
return
NULL
;
}
}
Py_DECREF
(
offset1
);
Py_DECREF
(
offset2
);
delta_d
=
ymd_to_ord
(
GET_YEAR
(
left
),
GET_MONTH
(
left
),
GET_DAY
(
left
))
-
...
...
@@ -4569,11 +4477,13 @@ datetime_subtract(PyObject *left, PyObject *right)
DATE_GET_SECOND
(
right
));
delta_us
=
DATE_GET_MICROSECOND
(
left
)
-
DATE_GET_MICROSECOND
(
right
);
/* (left - offset1) - (right - offset2) =
* (left - right) + (offset2 - offset1)
*/
delta_s
+=
(
offset2
-
offset1
)
*
60
;
result
=
new_delta
(
delta_d
,
delta_s
,
delta_us
,
1
);
if
(
offdiff
!=
NULL
)
{
PyObject
*
temp
=
result
;
result
=
delta_subtract
(
result
,
offdiff
);
Py_DECREF
(
temp
);
Py_DECREF
(
offdiff
);
}
}
else
if
(
PyDelta_Check
(
right
))
{
/* datetime - delta */
...
...
@@ -4683,9 +4593,9 @@ datetime_ctime(PyDateTime_DateTime *self)
static
PyObject
*
datetime_richcompare
(
PyObject
*
self
,
PyObject
*
other
,
int
op
)
{
PyObject
*
result
=
NULL
;
PyObject
*
offset1
,
*
offset2
;
int
diff
;
naivety
n1
,
n2
;
int
offset1
,
offset2
;
if
(
!
PyDateTime_Check
(
other
))
{
if
(
PyDate_Check
(
other
))
{
...
...
@@ -4706,85 +4616,99 @@ datetime_richcompare(PyObject *self, PyObject *other, int op)
return
Py_NotImplemented
;
}
if
(
classify_two_utcoffsets
(
self
,
&
offset1
,
&
n1
,
self
,
other
,
&
offset2
,
&
n2
,
other
)
<
0
)
if
(
GET_DT_TZINFO
(
self
)
==
GET_DT_TZINFO
(
other
))
{
diff
=
memcmp
(((
PyDateTime_DateTime
*
)
self
)
->
data
,
((
PyDateTime_DateTime
*
)
other
)
->
data
,
_PyDateTime_DATETIME_DATASIZE
);
return
diff_to_bool
(
diff
,
op
);
}
offset1
=
datetime_utcoffset
(
self
,
NULL
);
if
(
offset1
==
NULL
)
return
NULL
;
assert
(
n1
!=
OFFSET_UNKNOWN
&&
n2
!=
OFFSET_UNKNOWN
);
offset2
=
datetime_utcoffset
(
other
,
NULL
);
if
(
offset2
==
NULL
)
goto
done
;
/* If they're both naive, or both aware and have the same offsets,
* we get off cheap. Note that if they're both naive, offset1 ==
* offset2 ==
0
at this point.
* offset2 ==
Py_None
at this point.
*/
if
(
n1
==
n2
&&
offset1
==
offset2
)
{
if
((
offset1
==
offset2
)
||
(
PyDelta_Check
(
offset1
)
&&
PyDelta_Check
(
offset2
)
&&
delta_cmp
(
offset1
,
offset2
)
==
0
))
{
diff
=
memcmp
(((
PyDateTime_DateTime
*
)
self
)
->
data
,
((
PyDateTime_DateTime
*
)
other
)
->
data
,
_PyDateTime_DATETIME_DATASIZE
);
re
turn
diff_to_bool
(
diff
,
op
);
re
sult
=
diff_to_bool
(
diff
,
op
);
}
if
(
n1
==
OFFSET_AWARE
&&
n2
==
OFFSET_AWARE
)
{
else
if
(
offset1
!=
Py_None
&&
offset2
!=
Py_None
)
{
PyDateTime_Delta
*
delta
;
assert
(
offset1
!=
offset2
);
/* else last "if" handled it */
assert
(
offset1
!=
offset2
);
/* else last "if" handled it */
delta
=
(
PyDateTime_Delta
*
)
datetime_subtract
((
PyObject
*
)
self
,
other
);
if
(
delta
==
NULL
)
return
NULL
;
goto
done
;
diff
=
GET_TD_DAYS
(
delta
);
if
(
diff
==
0
)
diff
=
GET_TD_SECONDS
(
delta
)
|
GET_TD_MICROSECONDS
(
delta
);
Py_DECREF
(
delta
);
re
turn
diff_to_bool
(
diff
,
op
);
re
sult
=
diff_to_bool
(
diff
,
op
);
}
assert
(
n1
!=
n2
);
PyErr_SetString
(
PyExc_TypeError
,
"can't compare offset-naive and "
"offset-aware datetimes"
);
return
NULL
;
else
{
PyErr_SetString
(
PyExc_TypeError
,
"can't compare offset-naive and "
"offset-aware datetimes"
);
}
done:
Py_DECREF
(
offset1
);
Py_XDECREF
(
offset2
);
return
result
;
}
static
long
datetime_hash
(
PyDateTime_DateTime
*
self
)
{
if
(
self
->
hashcode
==
-
1
)
{
naivety
n
;
int
offset
;
PyObject
*
temp
;
n
=
classify_utcoffset
((
PyObject
*
)
self
,
(
PyObject
*
)
self
,
&
offset
);
assert
(
n
!=
OFFSET_UNKNOWN
);
if
(
n
==
OFFSET_ERROR
)
PyObject
*
offset
;
offset
=
datetime_utcoffset
((
PyObject
*
)
self
,
NULL
);
if
(
offset
==
NULL
)
return
-
1
;
/* Reduce this to a hash of another object. */
if
(
n
==
OFFSET_NAIVE
)
{
if
(
offset
==
Py_None
)
self
->
hashcode
=
generic_hash
(
(
unsigned
char
*
)
self
->
data
,
_PyDateTime_DATETIME_DATASIZE
);
return
self
->
hashcode
;
}
else
{
int
days
;
int
seconds
;
PyObject
*
temp1
,
*
temp2
;
int
days
,
seconds
;
assert
(
n
==
OFFSET_AWARE
);
assert
(
HASTZINFO
(
self
));
days
=
ymd_to_ord
(
GET_YEAR
(
self
),
GET_MONTH
(
self
),
GET_DAY
(
self
));
seconds
=
DATE_GET_HOUR
(
self
)
*
3600
+
(
DATE_GET_MINUTE
(
self
)
-
offset
)
*
60
+
DATE_GET_MINUTE
(
self
)
*
60
+
DATE_GET_SECOND
(
self
);
temp
=
new_delta
(
days
,
seconds
,
DATE_GET_MICROSECOND
(
self
),
1
);
}
if
(
temp
!=
NULL
)
{
self
->
hashcode
=
PyObject_Hash
(
temp
);
Py_DECREF
(
temp
);
temp1
=
new_delta
(
days
,
seconds
,
DATE_GET_MICROSECOND
(
self
),
1
);
if
(
temp1
==
NULL
)
{
Py_DECREF
(
offset
);
return
-
1
;
}
temp2
=
delta_subtract
(
temp1
,
offset
);
Py_DECREF
(
temp1
);
if
(
temp2
==
NULL
)
{
Py_DECREF
(
offset
);
return
-
1
;
}
self
->
hashcode
=
PyObject_Hash
(
temp2
);
Py_DECREF
(
temp2
);
}
Py_DECREF
(
offset
);
}
return
self
->
hashcode
;
}
...
...
@@ -4819,10 +4743,9 @@ datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
static
PyObject
*
datetime_astimezone
(
PyDateTime_DateTime
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
int
y
,
m
,
d
,
hh
,
mm
,
ss
,
us
;
PyObject
*
result
;
int
offset
,
none
;
PyObject
*
offset
;
PyObject
*
temp
;
PyObject
*
tzinfo
;
static
char
*
keywords
[]
=
{
"tz"
,
NULL
};
...
...
@@ -4840,39 +4763,35 @@ datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
}
/* Convert self to UTC. */
offset
=
call_utcoffset
(
self
->
tzinfo
,
(
PyObject
*
)
self
,
&
none
);
if
(
offset
==
-
1
&&
PyErr_Occurred
()
)
offset
=
datetime_utcoffset
((
PyObject
*
)
self
,
NULL
);
if
(
offset
==
NULL
)
return
NULL
;
if
(
none
)
goto
NeedAware
;
if
(
offset
==
Py_None
)
{
Py_DECREF
(
offset
);
NeedAware:
PyErr_SetString
(
PyExc_ValueError
,
"astimezone() cannot be applied to "
"a naive datetime"
);
return
NULL
;
}
y
=
GET_YEAR
(
self
);
m
=
GET_MONTH
(
self
);
d
=
GET_DAY
(
self
);
hh
=
DATE_GET_HOUR
(
self
);
mm
=
DATE_GET_MINUTE
(
self
);
ss
=
DATE_GET_SECOND
(
self
);
us
=
DATE_GET_MICROSECOND
(
self
);
mm
-=
offset
;
if
((
mm
<
0
||
mm
>=
60
)
&&
normalize_datetime
(
&
y
,
&
m
,
&
d
,
&
hh
,
&
mm
,
&
ss
,
&
us
)
<
0
)
/* result = self - offset */
result
=
add_datetime_timedelta
(
self
,
(
PyDateTime_Delta
*
)
offset
,
-
1
);
Py_DECREF
(
offset
);
if
(
result
==
NULL
)
return
NULL
;
/* Attach new tzinfo and let fromutc() do the rest. */
result
=
new_datetime
(
y
,
m
,
d
,
hh
,
mm
,
ss
,
us
,
tzinfo
);
if
(
result
!=
NULL
)
{
PyObject
*
temp
=
result
;
temp
=
((
PyDateTime_DateTime
*
)
result
)
->
tzinfo
;
((
PyDateTime_DateTime
*
)
result
)
->
tzinfo
=
tzinfo
;
Py_INCREF
(
tzinfo
);
Py_DECREF
(
temp
);
result
=
PyObject_CallMethod
(
tzinfo
,
"fromutc"
,
"O"
,
temp
);
Py_DECREF
(
temp
);
}
return
result
;
temp
=
result
;
result
=
PyObject_CallMethod
(
tzinfo
,
"fromutc"
,
"O"
,
temp
);
Py_DECREF
(
temp
);
NeedAware:
PyErr_SetString
(
PyExc_ValueError
,
"astimezone() cannot be applied to "
"a naive datetime"
);
return
NULL
;
return
result
;
}
static
PyObject
*
...
...
@@ -4881,17 +4800,15 @@ datetime_timetuple(PyDateTime_DateTime *self)
int
dstflag
=
-
1
;
if
(
HASTZINFO
(
self
)
&&
self
->
tzinfo
!=
Py_None
)
{
int
none
;
PyObject
*
dst
;
dst
flag
=
call_dst
(
self
->
tzinfo
,
(
PyObject
*
)
self
,
&
none
);
if
(
dst
flag
==
-
1
&&
PyErr_Occurred
()
)
dst
=
call_dst
(
self
->
tzinfo
,
(
PyObject
*
)
self
);
if
(
dst
==
NULL
)
return
NULL
;
if
(
none
)
dstflag
=
-
1
;
else
if
(
dstflag
!=
0
)
dstflag
=
1
;
if
(
dst
!=
Py_None
)
dstflag
=
delta_bool
((
PyDateTime_Delta
*
)
dst
);
Py_DECREF
(
dst
);
}
return
build_struct_time
(
GET_YEAR
(
self
),
GET_MONTH
(
self
),
...
...
@@ -4927,41 +4844,47 @@ datetime_gettimetz(PyDateTime_DateTime *self)
DATE_GET_MINUTE
(
self
),
DATE_GET_SECOND
(
self
),
DATE_GET_MICROSECOND
(
self
),
HASTZINFO
(
self
)
?
self
->
tzinfo
:
Py_None
);
GET_DT_TZINFO
(
self
)
);
}
static
PyObject
*
datetime_utctimetuple
(
PyDateTime_DateTime
*
self
)
{
int
y
=
GET_YEAR
(
self
);
int
m
=
GET_MONTH
(
self
);
int
d
=
GET_DAY
(
self
);
int
hh
=
DATE_GET_HOUR
(
self
);
int
mm
=
DATE_GET_MINUTE
(
self
);
int
ss
=
DATE_GET_SECOND
(
self
);
int
us
=
0
;
/* microseconds are ignored in a timetuple */
int
offset
=
0
;
if
(
HASTZINFO
(
self
)
&&
self
->
tzinfo
!=
Py_None
)
{
int
none
;
int
y
,
m
,
d
,
hh
,
mm
,
ss
;
PyObject
*
tzinfo
;
PyDateTime_DateTime
*
utcself
;
offset
=
call_utcoffset
(
self
->
tzinfo
,
(
PyObject
*
)
self
,
&
none
);
if
(
offset
==
-
1
&&
PyErr_Occurred
())
return
NULL
;
tzinfo
=
GET_DT_TZINFO
(
self
);
if
(
tzinfo
==
Py_None
)
{
utcself
=
self
;
Py_INCREF
(
utcself
);
}
/* Even if offset is 0, don't call timetuple() -- tm_isdst should be
* 0 in a UTC timetuple regardless of what dst() says.
*/
if
(
offset
)
{
/* Subtract offset minutes & normalize. */
int
stat
;
mm
-=
offset
;
stat
=
normalize_datetime
(
&
y
,
&
m
,
&
d
,
&
hh
,
&
mm
,
&
ss
,
&
us
);
/* OverflowError may be raised in the edge cases. */
if
(
stat
<
0
)
else
{
PyObject
*
offset
;
offset
=
call_utcoffset
(
tzinfo
,
(
PyObject
*
)
self
);
if
(
offset
==
NULL
)
return
NULL
;
if
(
offset
==
Py_None
)
{
Py_DECREF
(
offset
);
utcself
=
self
;
Py_INCREF
(
utcself
);
}
else
{
utcself
=
(
PyDateTime_DateTime
*
)
add_datetime_timedelta
(
self
,
(
PyDateTime_Delta
*
)
offset
,
-
1
);
Py_DECREF
(
offset
);
if
(
utcself
==
NULL
)
return
NULL
;
}
}
y
=
GET_YEAR
(
utcself
);
m
=
GET_MONTH
(
utcself
);
d
=
GET_DAY
(
utcself
);
hh
=
DATE_GET_HOUR
(
utcself
);
mm
=
DATE_GET_MINUTE
(
utcself
);
ss
=
DATE_GET_SECOND
(
utcself
);
Py_DECREF
(
utcself
);
return
build_struct_time
(
y
,
m
,
d
,
hh
,
mm
,
ss
,
0
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment