best-doctor / restdoctor

BestDoctor's batteries for REST services
MIT License
35 stars 23 forks source link

Dead timestamp #170

Open stepan-fedorovv opened 6 months ago

stepan-fedorovv commented 6 months ago

https://github.com/best-doctor/restdoctor/blob/master/restdoctor/rest_framework/fields.py#L15

class DateTimeField(BaseDateTimeField):
    def to_representation(
        self, value: datetime.datetime,
    ) -> Union[Optional[str], datetime.datetime]:
        if not value:
            return None

        output_format = getattr(self, 'format', api_settings.DATETIME_FORMAT)

        if output_format is None or isinstance(value, str):
            return value

        value = self.enforce_timezone(value)

        if output_format.lower() == ISO_8601:
            value = value.isoformat(timespec='microseconds')
            return value
        return value.strftime(output_format)

python 3.12 не может использовать output_format со значением %s https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior У вас умер timestamp

class DateTimeField(BaseDateTimeField):
    def to_representation(
        self, value: datetime.datetime,
    ) -> typing.Union[typing.Optional[str], datetime.datetime]:
        if not value:
            return None

        output_format = getattr(self, 'format', api_settings.DATETIME_FORMAT)

        if output_format is None or isinstance(value, str):
            return value

        value = self.enforce_timezone(value)

        if output_format.lower() == ISO_8601:
            value = value.isoformat(timespec='microseconds')
            return value
        if output_format.lower() == "%s":
            return value.timestamp()
        return value.strftime(output_format)

???

sergey-jerzy commented 6 months ago

Спасибо, если это единственное, что умирает на 3.12, то несложно поправить, конечно. Вообще, дефолтный формат дат в DRF - ISO_8601. Мы исправляли это место только для изменения формата iso (добавляли туда microseconds).

Если пришлете PR - добавляйте сразу 3.12 в матрицу тестирования вот сюда и другие workflow.

sergey-jerzy commented 6 months ago
        if output_format.lower() == "%s":
            return value.timestamp()

я бы убрал тут lower, т.к. %S - вполне валидный формат (хоть и несколько безсполезный) для 3.12

sergey-jerzy commented 6 months ago

These may not be available on all platforms when used with the strftime() method. The ISO 8601 year and ISO 8601 week directives are not interchangeable with the year and week number directives above. Calling strptime() with incomplete or ambiguous ISO 8601 directives will raise a ValueError.

The full set of format codes supported varies across platforms, because Python calls the platform C library’s strftime() function, and platform variations are common. To see the full set of format codes supported on your platform, consult the strftime(3) documentation. There are also differences between platforms in handling of unsupported format specifiers.

Python 3.12.2 (main, Feb  6 2024, 20:19:44) [Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> d = datetime.now()
>>> d.strftime('%s')
'1710880202'
>>> d.timestamp()
1710880202.059459

Смысл в том, что %s - это зависимое от платформы поведение системного strftime и никак не относится к коду RestDoctor.

Если вы хотите поддержать вывод всех DateTimeField в таком формате, то можно ввести что-то типа stamp и поддержать его наряду с %s. А может быть кому-то полезно будет иметь таймстемп не в секундах, а в миллисекундах или микросекундах.