From 8c6a947a7c8d143e756b050c93d43cd9c8781b14 Mon Sep 17 00:00:00 2001 From: Lars van Vianen Date: Sat, 6 Jul 2024 17:46:39 +0200 Subject: [PATCH] Create field_model_ifc_timestamp.py --- .../fields/model/field_model_ifc_timestamp.py | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/django-ifc/fields/model/field_model_ifc_timestamp.py diff --git a/src/django-ifc/fields/model/field_model_ifc_timestamp.py b/src/django-ifc/fields/model/field_model_ifc_timestamp.py new file mode 100644 index 0000000..27bbd3a --- /dev/null +++ b/src/django-ifc/fields/model/field_model_ifc_timestamp.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- + + +# ============================================================================= +# Docstring +# ============================================================================= + +""" +Provides IFC Timestamp Model Field Class +=================================== + + +https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ifcmeasureresource/lexical/ifctimestamp.htm + +""" # noqa E501 + + +# ============================================================================= +# Import +# ============================================================================= + +# Import | Standard Library +import datetime + +# Import | Libraries +from django.db import models +from django.utils.timezone import make_aware, get_default_timezone +from django.core.exceptions import ValidationError +from django.utils.translation import gettext_lazy as _ + +# Import | Local Modules + + +# ============================================================================= +# Variables +# ============================================================================= + +__all__ = ["IfcTimestampField", ] + + +# ============================================================================= +# Classes +# ============================================================================= + +class IfcTimestampField(models.TextField): + """ + IFC Timestamp Model Field Class + =============================== + + Custom Django field for storing IfcTimeStamp, which is the number of + seconds since 00:00:00 Coordinated Universal Time (UTC), Thursday, + 1 January 1970. + + This field stores the time as an integer but interacts with Python's + datetime objects, automatically handling conversion between these for + ease of use within Django. + + """ + + def from_db_value(self, value, expression, connection): + """ + Convert an integer from the database to a datetime.datetime object. + """ + if value is None: + return value + try: + return make_aware( + datetime.datetime.utcfromtimestamp(value), + get_default_timezone() + ) + # Handle overflow error which can happen with large timestamps + except OverflowError: + raise ValidationError( + _("Timestamp value is out of range for datetime.") + ) + + def to_python(self, value): + """ + Convert the value to a datetime.datetime object. + """ + if isinstance(value, datetime.datetime): + return value + if value is None: + return value + try: + return make_aware( + datetime.datetime.utcfromtimestamp(int(value)), + get_default_timezone() + ) + except (ValueError, OverflowError): + raise ValidationError(_("Invalid timestamp value.")) + + def get_prep_value(self, value): + """ + Convert the datetime.datetime object to an integer timestamp before + saving to the database. + """ + if isinstance(value, datetime.datetime): + return int(value.timestamp()) + return value + + def value_to_string(self, obj): + """ + Convert the datetime value to a string for serialization. + """ + value = self.value_from_object(obj) + return str( + int(value.timestamp()) + ) if isinstance(value, datetime.datetime) else ''