datetime.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. """Immutable datetime and date vars."""
  2. from __future__ import annotations
  3. import dataclasses
  4. import sys
  5. from datetime import date, datetime
  6. from typing import Any, NoReturn, TypeVar, Union, overload
  7. from reflex.utils.exceptions import VarTypeError
  8. from reflex.vars.number import BooleanVar
  9. from .base import (
  10. CustomVarOperationReturn,
  11. LiteralVar,
  12. Var,
  13. VarData,
  14. var_operation,
  15. var_operation_return,
  16. )
  17. DATETIME_T = TypeVar("DATETIME_T", datetime, date)
  18. datetime_types = Union[datetime, date]
  19. def raise_var_type_error():
  20. """Raise a VarTypeError.
  21. Raises:
  22. VarTypeError: Cannot compare a datetime object with a non-datetime object.
  23. """
  24. raise VarTypeError("Cannot compare a datetime object with a non-datetime object.")
  25. class DateTimeVar(Var[DATETIME_T], python_types=(datetime, date)):
  26. """A variable that holds a datetime or date object."""
  27. @overload
  28. def __lt__(self, other: datetime_types) -> BooleanVar: ...
  29. @overload
  30. def __lt__(self, other: NoReturn) -> NoReturn: ...
  31. def __lt__(self, other: Any):
  32. """Less than comparison.
  33. Args:
  34. other: The other datetime to compare.
  35. Returns:
  36. The result of the comparison.
  37. """
  38. if not isinstance(other, DATETIME_TYPES):
  39. raise_var_type_error()
  40. return date_lt_operation(self, other)
  41. @overload
  42. def __le__(self, other: datetime_types) -> BooleanVar: ...
  43. @overload
  44. def __le__(self, other: NoReturn) -> NoReturn: ...
  45. def __le__(self, other: Any):
  46. """Less than or equal comparison.
  47. Args:
  48. other: The other datetime to compare.
  49. Returns:
  50. The result of the comparison.
  51. """
  52. if not isinstance(other, DATETIME_TYPES):
  53. raise_var_type_error()
  54. return date_le_operation(self, other)
  55. @overload
  56. def __gt__(self, other: datetime_types) -> BooleanVar: ...
  57. @overload
  58. def __gt__(self, other: NoReturn) -> NoReturn: ...
  59. def __gt__(self, other: Any):
  60. """Greater than comparison.
  61. Args:
  62. other: The other datetime to compare.
  63. Returns:
  64. The result of the comparison.
  65. """
  66. if not isinstance(other, DATETIME_TYPES):
  67. raise_var_type_error()
  68. return date_gt_operation(self, other)
  69. @overload
  70. def __ge__(self, other: datetime_types) -> BooleanVar: ...
  71. @overload
  72. def __ge__(self, other: NoReturn) -> NoReturn: ...
  73. def __ge__(self, other: Any):
  74. """Greater than or equal comparison.
  75. Args:
  76. other: The other datetime to compare.
  77. Returns:
  78. The result of the comparison.
  79. """
  80. if not isinstance(other, DATETIME_TYPES):
  81. raise_var_type_error()
  82. return date_ge_operation(self, other)
  83. @var_operation
  84. def date_gt_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationReturn:
  85. """Greater than comparison.
  86. Args:
  87. lhs: The left-hand side of the operation.
  88. rhs: The right-hand side of the operation.
  89. Returns:
  90. The result of the operation.
  91. """
  92. return date_compare_operation(rhs, lhs, strict=True)
  93. @var_operation
  94. def date_lt_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationReturn:
  95. """Less than comparison.
  96. Args:
  97. lhs: The left-hand side of the operation.
  98. rhs: The right-hand side of the operation.
  99. Returns:
  100. The result of the operation.
  101. """
  102. return date_compare_operation(lhs, rhs, strict=True)
  103. @var_operation
  104. def date_le_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationReturn:
  105. """Less than or equal comparison.
  106. Args:
  107. lhs: The left-hand side of the operation.
  108. rhs: The right-hand side of the operation.
  109. Returns:
  110. The result of the operation.
  111. """
  112. return date_compare_operation(lhs, rhs)
  113. @var_operation
  114. def date_ge_operation(lhs: Var | Any, rhs: Var | Any) -> CustomVarOperationReturn:
  115. """Greater than or equal comparison.
  116. Args:
  117. lhs: The left-hand side of the operation.
  118. rhs: The right-hand side of the operation.
  119. Returns:
  120. The result of the operation.
  121. """
  122. return date_compare_operation(rhs, lhs)
  123. def date_compare_operation(
  124. lhs: DateTimeVar[DATETIME_T] | Any,
  125. rhs: DateTimeVar[DATETIME_T] | Any,
  126. strict: bool = False,
  127. ) -> CustomVarOperationReturn:
  128. """Check if the value is less than the other value.
  129. Args:
  130. lhs: The left-hand side of the operation.
  131. rhs: The right-hand side of the operation.
  132. strict: Whether to use strict comparison.
  133. Returns:
  134. The result of the operation.
  135. """
  136. return var_operation_return(
  137. f"({lhs} { '<' if strict else '<='} {rhs})",
  138. bool,
  139. )
  140. @dataclasses.dataclass(
  141. eq=False,
  142. frozen=True,
  143. **{"slots": True} if sys.version_info >= (3, 10) else {},
  144. )
  145. class LiteralDatetimeVar(LiteralVar, DateTimeVar):
  146. """Base class for immutable datetime and date vars."""
  147. _var_value: datetime | date = dataclasses.field(default=datetime.now())
  148. @classmethod
  149. def create(cls, value: datetime | date, _var_data: VarData | None = None):
  150. """Create a new instance of the class.
  151. Args:
  152. value: The value to set.
  153. Returns:
  154. LiteralDatetimeVar: The new instance of the class.
  155. """
  156. js_expr = f'"{value!s}"'
  157. return cls(
  158. _js_expr=js_expr,
  159. _var_type=type(value),
  160. _var_value=value,
  161. _var_data=_var_data,
  162. )
  163. DATETIME_TYPES = (datetime, date, DateTimeVar)