@@ -520,6 +520,10 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None:
520520 "rfc-1123" : Serializer .serialize_rfc ,
521521 "unix-time" : Serializer .serialize_unix ,
522522 "duration" : Serializer .serialize_duration ,
523+ "duration-seconds-int" : Serializer .serialize_duration_seconds_int ,
524+ "duration-seconds-float" : Serializer .serialize_duration_seconds_float ,
525+ "duration-milliseconds-int" : Serializer .serialize_duration_milliseconds_int ,
526+ "duration-milliseconds-float" : Serializer .serialize_duration_milliseconds_float ,
523527 "date" : Serializer .serialize_date ,
524528 "time" : Serializer .serialize_time ,
525529 "decimal" : Serializer .serialize_decimal ,
@@ -1109,6 +1113,61 @@ def serialize_duration(attr, **kwargs): # pylint: disable=unused-argument
11091113 attr = isodate .parse_duration (attr )
11101114 return isodate .duration_isoformat (attr )
11111115
1116+ @staticmethod
1117+ def _serialize_duration_numeric (attr , scale , as_int ):
1118+ """Serialize a TimeDelta into a numeric value scaled to the wire unit.
1119+
1120+ :param TimeDelta attr: Object to be serialized.
1121+ :param int scale: Multiplier applied to total seconds (1 for seconds, 1000 for milliseconds).
1122+ :param bool as_int: Whether to truncate the result to an int.
1123+ :rtype: int or float
1124+ :return: serialized duration
1125+ """
1126+ if isinstance (attr , str ):
1127+ attr = isodate .parse_duration (attr )
1128+ value = attr .total_seconds () * scale if isinstance (attr , datetime .timedelta ) else attr
1129+ return int (value ) if as_int else float (value )
1130+
1131+ @staticmethod
1132+ def serialize_duration_seconds_int (attr , ** kwargs ): # pylint: disable=unused-argument
1133+ """Serialize TimeDelta object into an integer number of seconds.
1134+
1135+ :param TimeDelta attr: Object to be serialized.
1136+ :rtype: int
1137+ :return: serialized duration
1138+ """
1139+ return Serializer ._serialize_duration_numeric (attr , 1 , True )
1140+
1141+ @staticmethod
1142+ def serialize_duration_seconds_float (attr , ** kwargs ): # pylint: disable=unused-argument
1143+ """Serialize TimeDelta object into a floating point number of seconds.
1144+
1145+ :param TimeDelta attr: Object to be serialized.
1146+ :rtype: float
1147+ :return: serialized duration
1148+ """
1149+ return Serializer ._serialize_duration_numeric (attr , 1 , False )
1150+
1151+ @staticmethod
1152+ def serialize_duration_milliseconds_int (attr , ** kwargs ): # pylint: disable=unused-argument
1153+ """Serialize TimeDelta object into an integer number of milliseconds.
1154+
1155+ :param TimeDelta attr: Object to be serialized.
1156+ :rtype: int
1157+ :return: serialized duration
1158+ """
1159+ return Serializer ._serialize_duration_numeric (attr , 1000 , True )
1160+
1161+ @staticmethod
1162+ def serialize_duration_milliseconds_float (attr , ** kwargs ): # pylint: disable=unused-argument
1163+ """Serialize TimeDelta object into a floating point number of milliseconds.
1164+
1165+ :param TimeDelta attr: Object to be serialized.
1166+ :rtype: float
1167+ :return: serialized duration
1168+ """
1169+ return Serializer ._serialize_duration_numeric (attr , 1000 , False )
1170+
11121171 @staticmethod
11131172 def serialize_rfc (attr , ** kwargs ): # pylint: disable=unused-argument
11141173 """Serialize Datetime object into RFC-1123 formatted string.
@@ -1381,6 +1440,10 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None:
13811440 "rfc-1123" : Deserializer .deserialize_rfc ,
13821441 "unix-time" : Deserializer .deserialize_unix ,
13831442 "duration" : Deserializer .deserialize_duration ,
1443+ "duration-seconds-int" : Deserializer .deserialize_duration_seconds ,
1444+ "duration-seconds-float" : Deserializer .deserialize_duration_seconds ,
1445+ "duration-milliseconds-int" : Deserializer .deserialize_duration_milliseconds ,
1446+ "duration-milliseconds-float" : Deserializer .deserialize_duration_milliseconds ,
13841447 "date" : Deserializer .deserialize_date ,
13851448 "time" : Deserializer .deserialize_time ,
13861449 "decimal" : Deserializer .deserialize_decimal ,
@@ -1393,6 +1456,10 @@ def __init__(self, classes: Optional[Mapping[str, type]] = None) -> None:
13931456 }
13941457 self .deserialize_expected_types = {
13951458 "duration" : (isodate .Duration , datetime .timedelta ),
1459+ "duration-seconds-int" : (isodate .Duration , datetime .timedelta ),
1460+ "duration-seconds-float" : (isodate .Duration , datetime .timedelta ),
1461+ "duration-milliseconds-int" : (isodate .Duration , datetime .timedelta ),
1462+ "duration-milliseconds-float" : (isodate .Duration , datetime .timedelta ),
13961463 "iso-8601" : (datetime .datetime ),
13971464 }
13981465 self .dependencies : dict [str , type ] = dict (classes ) if classes else {}
@@ -1954,6 +2021,48 @@ def deserialize_duration(attr):
19542021 raise DeserializationError (msg ) from err
19552022 return duration
19562023
2024+ @staticmethod
2025+ def _deserialize_duration_numeric (attr , unit ):
2026+ """Deserialize a numeric duration value into a TimeDelta object.
2027+
2028+ :param float attr: response value to be deserialized.
2029+ :param str unit: The wire unit, used as the ``timedelta`` keyword
2030+ (``"seconds"`` or ``"milliseconds"``).
2031+ :return: Deserialized duration
2032+ :rtype: TimeDelta
2033+ :raises DeserializationError: if value is invalid.
2034+ """
2035+ if isinstance (attr , ET .Element ):
2036+ attr = attr .text
2037+ try :
2038+ duration = datetime .timedelta (** {unit : float (attr )}) # type: ignore
2039+ except (ValueError , OverflowError , TypeError ) as err :
2040+ msg = "Cannot deserialize duration object."
2041+ raise DeserializationError (msg ) from err
2042+ return duration
2043+
2044+ @staticmethod
2045+ def deserialize_duration_seconds (attr ):
2046+ """Deserialize a numeric number of seconds into a TimeDelta object.
2047+
2048+ :param float attr: response value to be deserialized.
2049+ :return: Deserialized duration
2050+ :rtype: TimeDelta
2051+ :raises DeserializationError: if value is invalid.
2052+ """
2053+ return Deserializer ._deserialize_duration_numeric (attr , "seconds" )
2054+
2055+ @staticmethod
2056+ def deserialize_duration_milliseconds (attr ):
2057+ """Deserialize a numeric number of milliseconds into a TimeDelta object.
2058+
2059+ :param float attr: response value to be deserialized.
2060+ :return: Deserialized duration
2061+ :rtype: TimeDelta
2062+ :raises DeserializationError: if value is invalid.
2063+ """
2064+ return Deserializer ._deserialize_duration_numeric (attr , "milliseconds" )
2065+
19572066 @staticmethod
19582067 def deserialize_date (attr ):
19592068 """Deserialize ISO-8601 formatted string into Date object.
0 commit comments