datetime.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. """Immutable datetime and date vars."""
  2. from __future__ import annotations
  3. import dataclasses
  4. from datetime import date, datetime
  5. from typing import TypeVar, Union
  6. from .base import (
  7. CustomVarOperationReturn,
  8. LiteralVar,
  9. Var,
  10. VarData,
  11. var_operation,
  12. var_operation_return,
  13. )
  14. DATETIME_T = TypeVar("DATETIME_T", datetime, date)
  15. datetime_types = Union[datetime, date]
  16. def date_compare_operation(
  17. lhs: Var[datetime_types],
  18. rhs: Var[datetime_types],
  19. strict: bool = False,
  20. ) -> CustomVarOperationReturn[bool]:
  21. """Check if the value is less than the other value.
  22. Args:
  23. lhs: The left-hand side of the operation.
  24. rhs: The right-hand side of the operation.
  25. strict: Whether to use strict comparison.
  26. Returns:
  27. The result of the operation.
  28. """
  29. return var_operation_return(
  30. f"({lhs} {'<' if strict else '<='} {rhs})",
  31. bool,
  32. )
  33. @var_operation
  34. def date_gt_operation(
  35. lhs: Var[datetime_types],
  36. rhs: Var[datetime_types],
  37. ) -> CustomVarOperationReturn:
  38. """Greater than comparison.
  39. Args:
  40. lhs: The left-hand side of the operation.
  41. rhs: The right-hand side of the operation.
  42. Returns:
  43. The result of the operation.
  44. """
  45. return date_compare_operation(rhs, lhs, strict=True)
  46. @var_operation
  47. def date_lt_operation(
  48. lhs: Var[datetime_types],
  49. rhs: Var[datetime_types],
  50. ) -> CustomVarOperationReturn:
  51. """Less than comparison.
  52. Args:
  53. lhs: The left-hand side of the operation.
  54. rhs: The right-hand side of the operation.
  55. Returns:
  56. The result of the operation.
  57. """
  58. return date_compare_operation(lhs, rhs, strict=True)
  59. @var_operation
  60. def date_le_operation(
  61. lhs: Var[datetime_types], rhs: Var[datetime_types]
  62. ) -> CustomVarOperationReturn:
  63. """Less than or equal comparison.
  64. Args:
  65. lhs: The left-hand side of the operation.
  66. rhs: The right-hand side of the operation.
  67. Returns:
  68. The result of the operation.
  69. """
  70. return date_compare_operation(lhs, rhs)
  71. @var_operation
  72. def date_ge_operation(
  73. lhs: Var[datetime_types], rhs: Var[datetime_types]
  74. ) -> CustomVarOperationReturn:
  75. """Greater than or equal comparison.
  76. Args:
  77. lhs: The left-hand side of the operation.
  78. rhs: The right-hand side of the operation.
  79. Returns:
  80. The result of the operation.
  81. """
  82. return date_compare_operation(rhs, lhs)
  83. class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)):
  84. """A variable that holds a datetime or date object."""
  85. __lt__ = date_lt_operation
  86. __le__ = date_le_operation
  87. __gt__ = date_gt_operation
  88. __ge__ = date_ge_operation
  89. @dataclasses.dataclass(
  90. eq=False,
  91. frozen=True,
  92. slots=True,
  93. )
  94. class LiteralDatetimeVar(LiteralVar, DateTimeVar):
  95. """Base class for immutable datetime and date vars."""
  96. _var_value: datetime | date = dataclasses.field(default=datetime.now())
  97. @classmethod
  98. def create(cls, value: datetime | date, _var_data: VarData | None = None):
  99. """Create a new instance of the class.
  100. Args:
  101. value: The value to set.
  102. Returns:
  103. LiteralDatetimeVar: The new instance of the class.
  104. """
  105. js_expr = f'"{value!s}"'
  106. return cls(
  107. _js_expr=js_expr,
  108. _var_type=type(value),
  109. _var_value=value,
  110. _var_data=_var_data,
  111. )
  112. DATETIME_TYPES = (datetime, date, DateTimeVar)