summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthon van der Neut <anthon@mnt.org>2022-01-03 09:22:25 +0100
committerAnthon van der Neut <anthon@mnt.org>2022-01-03 09:22:25 +0100
commit25f75a2cbbc0425b722d85117cd611f498f48cea (patch)
tree448eb5d177d88a7c86ac9bfb4c3884513ad43367
parent285a927e0b675d7b67d7d893e3b86862784fb0fb (diff)
downloadruamel.yaml-25f75a2cbbc0425b722d85117cd611f498f48cea.tar.gz
fix issue 414 dateime fraction >= 99999950.17.20
-rw-r--r--CHANGES4
-rw-r--r--LICENSE2
-rw-r--r--README.rst8
-rw-r--r--__init__.py6
-rw-r--r--_doc/_static/pypi.svg2
-rw-r--r--_test/test_datetime.py13
-rw-r--r--constructor.py22
-rw-r--r--emitter.py2
-rw-r--r--util.py15
9 files changed, 45 insertions, 29 deletions
diff --git a/CHANGES b/CHANGES
index 2be1fe5..a921b1e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+[0, 17, 20]: today
+ - fix error in microseconds while rounding datetime fractions >= 9999995
+ (reported by `Luis Ferreira <https://sourceforge.net/u/ljmf00/>`__)
+
[0, 17, 19]: 2021-12-26
- fix mypy problems (reported by `Arun <https://sourceforge.net/u/arunppsg/profile/>`__)
diff --git a/LICENSE b/LICENSE
index 3f65b07..678f5cc 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
- Copyright (c) 2014-2021 Anthon van der Neut, Ruamel bvba
+ Copyright (c) 2014-2022 Anthon van der Neut, Ruamel bvba
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.rst b/README.rst
index 0e85970..e5100b9 100644
--- a/README.rst
+++ b/README.rst
@@ -4,8 +4,8 @@ ruamel.yaml
``ruamel.yaml`` is a YAML 1.2 loader/dumper package for Python.
-:version: 0.17.19
-:updated: 2021-12-26
+:version: 0.17.20
+:updated: today
:documentation: http://yaml.readthedocs.io
:repository: https://sourceforge.net/projects/ruamel-yaml/
:pypi: https://pypi.org/project/ruamel.yaml/
@@ -72,6 +72,10 @@ ChangeLog
.. should insert NEXT: at the beginning of line for next key (with empty line)
+0.17.20 (today):
+ - fix error in microseconds while rounding datetime fractions >= 9999995
+ (reported by `Luis Ferreira <https://sourceforge.net/u/ljmf00/>`__)
+
0.17.19 (2021-12-26):
- fix mypy problems (reported by `Arun <https://sourceforge.net/u/arunppsg/profile/>`__)
diff --git a/__init__.py b/__init__.py
index 3666b0b..4e95b86 100644
--- a/__init__.py
+++ b/__init__.py
@@ -5,9 +5,9 @@ if False: # MYPY
_package_data = dict(
full_package_name='ruamel.yaml',
- version_info=(0, 17, 19),
- __version__='0.17.19',
- version_timestamp='2021-12-26 16:02:42',
+ version_info=(0, 17, 20),
+ __version__='0.17.20',
+ version_timestamp='2022-01-03 09:19:48',
author='Anthon van der Neut',
author_email='a.van.der.neut@ruamel.eu',
description='ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order', # NOQA
diff --git a/_doc/_static/pypi.svg b/_doc/_static/pypi.svg
index cd5be20..85bfab9 100644
--- a/_doc/_static/pypi.svg
+++ b/_doc/_static/pypi.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h33v20H0z"/><path fill="#007ec6" d="M33 0h53v20H33z"/><path fill="url(#b)" d="M0 0h86v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">pypi</text><text x="175" y="140" transform="scale(.1)" textLength="230">pypi</text><text x="585" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">0.17.19</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.17.19</text></g> </svg>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h33v20H0z"/><path fill="#007ec6" d="M33 0h53v20H33z"/><path fill="url(#b)" d="M0 0h86v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">pypi</text><text x="175" y="140" transform="scale(.1)" textLength="230">pypi</text><text x="585" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">0.17.20</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.17.20</text></g> </svg>
diff --git a/_test/test_datetime.py b/_test/test_datetime.py
index 5874c0d..7321816 100644
--- a/_test/test_datetime.py
+++ b/_test/test_datetime.py
@@ -145,3 +145,16 @@ class TestDateTime:
""")
data = copy.deepcopy(round_trip_load(x))
assert round_trip_dump(data) == x
+
+ def test_fraction_overflow(self):
+ # reported (indirectly) by Luís Ferreira
+ # https://sourceforge.net/p/ruamel-yaml/tickets/414/
+ inp = dedent("""\
+ - 2022-01-02T12:34:59.9999994
+ - 2022-01-02T12:34:59.9999995
+ """)
+ exp = dedent("""\
+ - 2022-01-02T12:34:59.999999
+ - 2022-01-02T12:35:00
+ """)
+ round_trip(inp, exp)
diff --git a/constructor.py b/constructor.py
index 6049c0c..6aa6371 100644
--- a/constructor.py
+++ b/constructor.py
@@ -1759,20 +1759,7 @@ class RoundTripConstructor(SafeConstructor):
else:
return create_timestamp(**values)
# return SafeConstructor.construct_yaml_timestamp(self, node, values)
- year = int(values['year'])
- month = int(values['month'])
- day = int(values['day'])
- hour = int(values['hour'])
- minute = int(values['minute'])
- second = int(values['second'])
- fraction = 0
- if values['fraction']:
- fraction_s = values['fraction'][:6]
- while len(fraction_s) < 6:
- fraction_s += '0'
- fraction = int(fraction_s)
- if len(values['fraction']) > 6 and int(values['fraction'][6]) > 4:
- fraction += 1
+ dd = create_timestamp(**values) # this has delta applied
delta = None
if values['tz_sign']:
tz_hour = int(values['tz_hour'])
@@ -1782,17 +1769,16 @@ class RoundTripConstructor(SafeConstructor):
if values['tz_sign'] == '-':
delta = -delta
# should check for None and solve issue 366 should be tzinfo=delta)
+ data = TimeStamp(
+ dd.year, dd.month, dd.day, dd.hour, dd.minute, dd.second, dd.microsecond
+ )
if delta:
- dt = datetime.datetime(year, month, day, hour, minute)
- dt -= delta
- data = TimeStamp(dt.year, dt.month, dt.day, dt.hour, dt.minute, second, fraction)
data._yaml['delta'] = delta
tz = values['tz_sign'] + values['tz_hour']
if values['tz_minute']:
tz += ':' + values['tz_minute']
data._yaml['tz'] = tz
else:
- data = TimeStamp(year, month, day, hour, minute, second, fraction)
if values['tz']: # no delta
data._yaml['tz'] = values['tz']
diff --git a/emitter.py b/emitter.py
index 06de29c..f9611ee 100644
--- a/emitter.py
+++ b/emitter.py
@@ -76,7 +76,7 @@ class Indents:
def seq_flow_align(self, seq_indent, column, pre_comment=False):
# type: (int, int, Optional[bool]) -> int
# extra spaces because of dash
- nprint('seq_flow_align', self.values, pre_comment)
+ # nprint('seq_flow_align', self.values, pre_comment)
if len(self.values) < 2 or not self.values[-1][1]:
if len(self.values) == 0 or not pre_comment:
return 0
diff --git a/util.py b/util.py
index f3a96a1..9ff51bd 100644
--- a/util.py
+++ b/util.py
@@ -68,6 +68,8 @@ def create_timestamp(
year, month, day, t, hour, minute, second, fraction, tz, tz_sign, tz_hour, tz_minute
):
# type: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any) -> Any
+ # create a timestamp from match against timestamp_regexp
+ MAX_FRAC = 999999
year = int(year)
month = int(month)
day = int(day)
@@ -76,24 +78,31 @@ def create_timestamp(
hour = int(hour)
minute = int(minute)
second = int(second)
+ frac = 0
if fraction:
- frac = 0
frac_s = fraction[:6]
while len(frac_s) < 6:
frac_s += '0'
frac = int(frac_s)
if len(fraction) > 6 and int(fraction[6]) > 4:
frac += 1
- fraction = frac
+ if frac > MAX_FRAC:
+ fraction = 0
+ else:
+ fraction = frac
else:
fraction = 0
delta = None
if tz_sign:
tz_hour = int(tz_hour)
tz_minute = int(tz_minute) if tz_minute else 0
- delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute)
+ delta = datetime.timedelta(
+ hours=tz_hour, minutes=tz_minute, seconds=1 if frac > MAX_FRAC else 0
+ )
if tz_sign == '-':
delta = -delta
+ elif frac > MAX_FRAC:
+ delta = -datetime.timedelta(seconds=1)
# should do something else instead (or hook this up to the preceding if statement
# in reverse
# if delta is None: