From 0a2236b09b9f0c53179c13ecffc5272a59ccea98 Mon Sep 17 00:00:00 2001 From: Christopher McEvoy <12284065+chrisimcevoy@users.noreply.github.com> Date: Sat, 25 May 2024 23:03:46 +0100 Subject: [PATCH] feat: use `InstantPattern` in `Instant.__repr__` --- pyoda_time/_instant.py | 15 +++++---------- pyoda_time/globalization/_pyoda_format_info.py | 15 ++++++++++++++- pyoda_time/text/_instant_pattern.py | 8 ++++---- pyoda_time/time_zones/_zone_interval.py | 8 +++++--- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/pyoda_time/_instant.py b/pyoda_time/_instant.py index be9c473..31e17b9 100644 --- a/pyoda_time/_instant.py +++ b/pyoda_time/_instant.py @@ -472,13 +472,8 @@ def in_utc(self) -> ZonedDateTime: ) return ZonedDateTime._ctor(offset_date_time=offset_date_time, zone=DateTimeZone.utc) - def __str__(self) -> str: - if not self._is_valid: - if self == self._before_min_value(): - # TODO: Instant._before_min_value.__str__() - return super().__str__() - if self == self._after_max_value(): - # TODO: Instant._after_max_value.__str__() - return super().__str__() - ldt = self.in_utc().local_date_time - return f"{ldt.year:0>4}-{ldt.month:0>2}-{ldt.day:0>2}T{ldt.hour:0>2}:{ldt.minute:0>2}:{ldt.second:0>2}Z" + def __repr__(self) -> str: + from pyoda_time._compatibility._culture_info import CultureInfo + from pyoda_time.text import InstantPattern + + return InstantPattern._bcl_support.format(self, None, CultureInfo.current_culture) diff --git a/pyoda_time/globalization/_pyoda_format_info.py b/pyoda_time/globalization/_pyoda_format_info.py index d8ceadb..27a90ad 100644 --- a/pyoda_time/globalization/_pyoda_format_info.py +++ b/pyoda_time/globalization/_pyoda_format_info.py @@ -191,7 +191,20 @@ def _offset_pattern_parser(self) -> _FixedFormatInfoPatternParser[Offset]: @property def _instant_pattern_parser(self) -> _FixedFormatInfoPatternParser[Instant]: - raise NotImplementedError + if self.__instant_pattern_parser is None: + with self.__FIELD_LOCK: + if self.__instant_pattern_parser is None: + from pyoda_time.text import InstantPattern, LocalDatePattern + from pyoda_time.text._fixed_format_info_pattern_parser import _FixedFormatInfoPatternParser + from pyoda_time.text._instant_pattern_parser import _InstantPatternParser + + self.__instant_pattern_parser = _FixedFormatInfoPatternParser( + _InstantPatternParser._ctor( + InstantPattern._DEFAULT_TEMPLATE_VALUE, LocalDatePattern._DEFAULT_TWO_DIGIT_YEAR_MAX + ), + self, + ) + return self.__instant_pattern_parser @property def _local_time_pattern_parser(self) -> _FixedFormatInfoPatternParser[LocalTime]: diff --git a/pyoda_time/text/_instant_pattern.py b/pyoda_time/text/_instant_pattern.py index 37ecc74..524155a 100644 --- a/pyoda_time/text/_instant_pattern.py +++ b/pyoda_time/text/_instant_pattern.py @@ -67,7 +67,7 @@ class __CombinedMeta(_ProtocolMeta, _InstantPatternMeta): class InstantPattern(IPattern[Instant], metaclass=__CombinedMeta): """Represents a pattern for parsing and formatting ``Instant`` values.""" - __DEFAULT_TEMPLATE_VALUE: Final[Instant] = Instant.from_utc(2000, 1, 1, 0, 0) + _DEFAULT_TEMPLATE_VALUE: Final[Instant] = Instant.from_utc(2000, 1, 1, 0, 0) __pattern: IPattern[Instant] __pattern_text: str @@ -164,7 +164,7 @@ def create(cls, pattern_text: str, culture_info: CultureInfo) -> InstantPattern: return cls.__create( pattern_text, _PyodaFormatInfo._get_format_info(culture_info), - cls.__DEFAULT_TEMPLATE_VALUE, + cls._DEFAULT_TEMPLATE_VALUE, LocalDatePattern._DEFAULT_TWO_DIGIT_YEAR_MAX, ) @@ -182,7 +182,7 @@ def create_with_current_culture(cls, pattern_text: str) -> InstantPattern: return cls.__create( pattern_text, _PyodaFormatInfo.current_info, - cls.__DEFAULT_TEMPLATE_VALUE, + cls._DEFAULT_TEMPLATE_VALUE, LocalDatePattern._DEFAULT_TWO_DIGIT_YEAR_MAX, ) @@ -198,7 +198,7 @@ def create_with_invariant_culture(cls, pattern_text: str) -> InstantPattern: return cls.__create( pattern_text, _PyodaFormatInfo.invariant_info, - cls.__DEFAULT_TEMPLATE_VALUE, + cls._DEFAULT_TEMPLATE_VALUE, LocalDatePattern._DEFAULT_TWO_DIGIT_YEAR_MAX, ) diff --git a/pyoda_time/time_zones/_zone_interval.py b/pyoda_time/time_zones/_zone_interval.py index 86688b4..fd1ed52 100644 --- a/pyoda_time/time_zones/_zone_interval.py +++ b/pyoda_time/time_zones/_zone_interval.py @@ -146,9 +146,10 @@ def __init__( end = Instant._after_max_value() _Preconditions._check_not_null(name, "name") - _Preconditions._check_argument( - start < end, "start", f"The start Instant must be less than the end Instant. start: {start}; end: {end}" - ) + if start >= end: # Needed to prevent infinite recursion calling Instant.__repr__ + _Preconditions._check_argument( + start < end, "start", f"The start Instant must be less than the end Instant. start: {start}; end: {end}" + ) self.__name: Final[str] = name self.__raw_start: Final[Instant] = start self.__raw_end: Final[Instant] = end @@ -187,6 +188,7 @@ def __contains__(self, instant: Instant) -> bool: def _contains(self, local_instant: _LocalInstant) -> bool: """Determines whether this period contains the given LocalInstant in its range.""" + # TODO: why is this not implemented in __contains__ above? # Implementation of ``internal bool Contains(LocalInstant localInstant)`` return self.__local_start <= local_instant < self.__local_end