Compare commits

...

2 Commits

Author SHA1 Message Date
jan 46b3349935 Allow reading files with invalid dates
Notably, KLayout writes invalid dates when told to not write the date
1 month ago
jan 97527a5948 specify signature instead of using astype 1 month ago

@ -3,12 +3,16 @@ Functionality for encoding/decoding basic datatypes
""" """
from typing import Sequence, IO from typing import Sequence, IO
import struct import struct
import logging
from datetime import datetime from datetime import datetime
import numpy import numpy
from numpy.typing import NDArray from numpy.typing import NDArray
logger = logging.getLogger(__name__)
class KlamathError(Exception): class KlamathError(Exception):
pass pass
@ -44,7 +48,7 @@ def decode_real8(nums: NDArray[numpy.uint64]) -> NDArray[numpy.float64]:
exp = (nums >> 56) & 0x7f exp = (nums >> 56) & 0x7f
mant = (nums & 0x00ff_ffff_ffff_ffff).astype(numpy.float64) mant = (nums & 0x00ff_ffff_ffff_ffff).astype(numpy.float64)
mant[neg != 0] *= -1 mant[neg != 0] *= -1
return numpy.ldexp(mant, (4 * (exp - 64) - 56).astype(numpy.int64)) return numpy.ldexp(mant, 4 * (exp - 64) - 56, signature=(float, int, float))
def parse_real8(data: bytes) -> NDArray[numpy.float64]: def parse_real8(data: bytes) -> NDArray[numpy.float64]:
@ -70,7 +74,12 @@ def parse_datetime(data: bytes) -> list[datetime]:
dts = [] dts = []
for ii in range(0, len(data), 12): for ii in range(0, len(data), 12):
year, *date_parts = parse_int2(data[ii:ii + 12]) year, *date_parts = parse_int2(data[ii:ii + 12])
dts.append(datetime(year + 1900, *date_parts)) try:
dt = datetime(year + 1900, *date_parts)
except ValueError as err:
dt = datetime(1900, 1, 1, 0, 0, 0)
logger.warning(f'Invalid date {[year] + date_parts}, setting {dt} instead')
dts.append(dt)
return dts return dts

@ -2,11 +2,12 @@ import struct
import pytest # type: ignore import pytest # type: ignore
import numpy import numpy
from datetime import datetime
from numpy.testing import assert_array_equal from numpy.testing import assert_array_equal
from .basic import parse_bitarray, parse_int2, parse_int4, parse_real8, parse_ascii from .basic import parse_bitarray, parse_int2, parse_int4, parse_real8, parse_ascii
from .basic import pack_bitarray, pack_int2, pack_int4, pack_real8, pack_ascii from .basic import pack_bitarray, pack_int2, pack_int4, pack_real8, pack_ascii
from .basic import decode_real8, encode_real8 from .basic import decode_real8, encode_real8, parse_datetime
from .basic import KlamathError from .basic import KlamathError
@ -117,3 +118,14 @@ def test_pack_real8():
def test_pack_ascii(): def test_pack_ascii():
assert pack_ascii(b'4321') == b'4321' assert pack_ascii(b'4321') == b'4321'
assert pack_ascii(b'321') == b'321\0' assert pack_ascii(b'321') == b'321\0'
def test_invalid_date():
default = [datetime(1900, 1, 1, 0, 0, 0)]
assert parse_datetime(pack_int2((0, 0, 0, 0, 0, 0))) == default
assert parse_datetime(pack_int2((0, 1, 32, 0, 0, 0))) == default
assert parse_datetime(pack_int2((0, 2, 30, 0, 0, 0))) == default
assert parse_datetime(pack_int2((0, 1, 1, 24, 0, 0))) == default
assert parse_datetime(pack_int2((0, 1, 1, 25, 0, 0))) == default
assert parse_datetime(pack_int2((0, 1, 1, 0, 61, 0))) == default
assert parse_datetime(pack_int2((0, 1, 1, 0, 0, 61))) == default

Loading…
Cancel
Save