Skip to content

Commit

Permalink
Avoid COM dates that end up with ms=1000, instead rounding to the nex…
Browse files Browse the repository at this point in the history
…t second. Fixes #1655. (#1683)
  • Loading branch information
mhammond committed May 7, 2021
1 parent e0a7d99 commit 5f1028f
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGES.txt
Expand Up @@ -11,6 +11,10 @@ Since build 300:
* Fix a bug in `win32profile.GetEnvironmentStrings()` relating to environment
variables with an equals sign (@maxim-krikun in #1661)

* Fixed a bug where certain COM dates would fail to be converted to a Python
datetime object with `ValueError: microsecond must be in 0..999999`. Shoutout
to @hujiaxing for reporting and helping reproduce the issue (#1655)

* Added win32com.shell.SHGetKnownFolderPath() and related constants.

* Shifted work in win32.lib.pywin32_bootstrap to Python's import system from
Expand Down
4 changes: 4 additions & 0 deletions com/win32com/test/testPyComTest.py
Expand Up @@ -273,6 +273,10 @@ def TestCommon(o, is_generated):
later = now + datetime.timedelta(seconds=1)
TestApplyResult(o.EarliestDate, (now, later), now)

# The below used to fail with `ValueError: microsecond must be in 0..999999` - see #1655
# https://planetcalc.com/7027/ says that float is: Sun, 25 Mar 1951 7:23:49 am
assert o.MakeDate(18712.308206013888) == datetime.datetime.fromisoformat("1951-03-25 07:23:49+00:00")

progress("Checking currency")
# currency.
pythoncom.__future_currency__ = 1
Expand Down
9 changes: 7 additions & 2 deletions win32/src/PyTime.cpp
Expand Up @@ -380,11 +380,16 @@ PyObject *PyWin_NewTime(PyObject *timeOb)
double minutes = (hours - (int)hours) * 60.0;
double seconds = round((minutes - (int)minutes) * 60.0, 4);
double milliseconds = round((seconds - (int)seconds) * 1000.0, 0);
// assert(milliseconds>=0.0 && milliseconds<=999.0);

// Strip off the msec part of time
double TimeWithoutMsecs = t - (ONETHOUSANDMILLISECONDS / 1000.0 * milliseconds);

// We might have rounded ms to 1000 which blows up datetime. Round up
// to the next second.
if (milliseconds >= 1000) {
TimeWithoutMsecs += ONETHOUSANDMILLISECONDS;
milliseconds = 0;
}

// Let the OS translate the variant date/time
SYSTEMTIME st;
if (!VariantTimeToSystemTime(TimeWithoutMsecs, &st)) {
Expand Down

0 comments on commit 5f1028f

Please sign in to comment.