Skip to content

Commit ef08a75

Browse files
committed
Do not include timezone if DateTimeKind is Unspecified
DECREF'ing datetime timezone argument when DateTimeKind is Unspecified was causing `Fatal Python error: deallocating None` because the object was set to `Runtime.PyNone`. Fixed the input to datetime constructor as we were passing milliseconds, where it should be microseconds.
1 parent c6db866 commit ef08a75

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

src/runtime/converter.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,15 +292,30 @@ internal static IntPtr ToPython(object value, Type type)
292292
case TypeCode.DateTime:
293293
var datetime = (DateTime)value;
294294

295-
IntPtr dateTimeArgs = Runtime.PyTuple_New(8);
295+
var tzInfo = TzInfo(datetime.Kind);
296+
297+
// Only add timezone (7th parameter) if not None (None means DateTimeKind.Unspecified).
298+
var size = tzInfo == Runtime.PyNone ? 7 : 8;
299+
300+
IntPtr dateTimeArgs = Runtime.PyTuple_New(size);
296301
Runtime.PyTuple_SetItem(dateTimeArgs, 0, Runtime.PyInt_FromInt32(datetime.Year));
297302
Runtime.PyTuple_SetItem(dateTimeArgs, 1, Runtime.PyInt_FromInt32(datetime.Month));
298303
Runtime.PyTuple_SetItem(dateTimeArgs, 2, Runtime.PyInt_FromInt32(datetime.Day));
299304
Runtime.PyTuple_SetItem(dateTimeArgs, 3, Runtime.PyInt_FromInt32(datetime.Hour));
300305
Runtime.PyTuple_SetItem(dateTimeArgs, 4, Runtime.PyInt_FromInt32(datetime.Minute));
301306
Runtime.PyTuple_SetItem(dateTimeArgs, 5, Runtime.PyInt_FromInt32(datetime.Second));
302-
Runtime.PyTuple_SetItem(dateTimeArgs, 6, Runtime.PyInt_FromInt32(datetime.Millisecond));
303-
Runtime.PyTuple_SetItem(dateTimeArgs, 7, TzInfo(datetime.Kind));
307+
308+
// datetime.datetime 6th argument represents micro seconds
309+
var totalSeconds = datetime.TimeOfDay.TotalSeconds;
310+
var microSeconds = Convert.ToInt32((totalSeconds - Math.Truncate(totalSeconds)) * 1000000);
311+
if (microSeconds == 1000000) microSeconds = 999999;
312+
Runtime.PyTuple_SetItem(dateTimeArgs, 6, Runtime.PyInt_FromInt32(microSeconds));
313+
314+
if (size == 8)
315+
{
316+
Runtime.PyTuple_SetItem(dateTimeArgs, 7, tzInfo);
317+
}
318+
304319
var returnDateTime = Runtime.PyObject_CallObject(dateTimeCtor, dateTimeArgs);
305320
// clean up
306321
Runtime.XDecref(dateTimeArgs);

0 commit comments

Comments
 (0)