|
45 | 45 | IntegerType, |
46 | 46 | LongType, |
47 | 47 | StringType, |
| 48 | + TimestampNanoType, |
48 | 49 | TimestampType, |
| 50 | + TimestamptzNanoType, |
49 | 51 | TimestamptzType, |
50 | 52 | TimeType, |
51 | 53 | UUIDType, |
|
56 | 58 | datetime_to_micros, |
57 | 59 | days_to_date, |
58 | 60 | micros_to_days, |
| 61 | + micros_to_nanos, |
59 | 62 | micros_to_timestamp, |
| 63 | + nanos_to_days, |
| 64 | + nanos_to_micros, |
| 65 | + nanos_to_timestamp, |
60 | 66 | time_str_to_micros, |
61 | 67 | time_to_micros, |
62 | 68 | timestamp_to_micros, |
| 69 | + timestamp_to_nanos, |
63 | 70 | timestamptz_to_micros, |
| 71 | + timestamptz_to_nanos, |
64 | 72 | ) |
65 | 73 | from pyiceberg.utils.decimal import decimal_to_unscaled, unscaled_to_decimal |
66 | 74 | from pyiceberg.utils.singleton import Singleton |
@@ -347,6 +355,16 @@ def _(self, _: TimestampType) -> Literal[int]: |
347 | 355 | def _(self, _: TimestamptzType) -> Literal[int]: |
348 | 356 | return TimestampLiteral(self.value) |
349 | 357 |
|
| 358 | + @to.register(TimestampNanoType) |
| 359 | + def _(self, type_var: TimestampNanoType) -> Literal[int]: |
| 360 | + # The value is assumed to be in microseconds, to match the TimestampType case above |
| 361 | + return TimestampLiteral(self.value).to(type_var) |
| 362 | + |
| 363 | + @to.register(TimestamptzNanoType) |
| 364 | + def _(self, type_var: TimestamptzNanoType) -> Literal[int]: |
| 365 | + # The value is assumed to be in microseconds, to match the TimestamptzType case above |
| 366 | + return TimestampLiteral(self.value).to(type_var) |
| 367 | + |
350 | 368 | @to.register(DecimalType) |
351 | 369 | def _(self, type_var: DecimalType) -> Literal[Decimal]: |
352 | 370 | unscaled = Decimal(self.value) |
@@ -495,6 +513,54 @@ def _(self, _: TimestamptzType) -> Literal[int]: |
495 | 513 | def _(self, _: DateType) -> Literal[int]: |
496 | 514 | return DateLiteral(micros_to_days(self.value)) |
497 | 515 |
|
| 516 | + @to.register(TimestampNanoType) |
| 517 | + def _(self, _: TimestampNanoType) -> Literal[int]: |
| 518 | + return TimestampNanoLiteral(micros_to_nanos(self.value)) |
| 519 | + |
| 520 | + @to.register(TimestamptzNanoType) |
| 521 | + def _(self, _: TimestamptzNanoType) -> Literal[int]: |
| 522 | + return TimestampNanoLiteral(micros_to_nanos(self.value)) |
| 523 | + |
| 524 | + |
| 525 | +class TimestampNanoLiteral(Literal[int]): |
| 526 | + def __init__(self, value: int) -> None: |
| 527 | + super().__init__(value, int) |
| 528 | + |
| 529 | + @model_serializer |
| 530 | + def ser_model(self) -> str: |
| 531 | + # Python datetime only goes down to microseconds, so the last three digits are appended |
| 532 | + return f"{nanos_to_timestamp(self.root).isoformat(timespec='microseconds')}{self.root % 1000:03d}" |
| 533 | + |
| 534 | + def increment(self) -> Literal[int]: |
| 535 | + return TimestampNanoLiteral(self.value + 1) |
| 536 | + |
| 537 | + def decrement(self) -> Literal[int]: |
| 538 | + return TimestampNanoLiteral(self.value - 1) |
| 539 | + |
| 540 | + @singledispatchmethod |
| 541 | + def to(self, type_var: IcebergType) -> Literal: # type: ignore |
| 542 | + raise TypeError(f"Cannot convert TimestampNanoLiteral into {type_var}") |
| 543 | + |
| 544 | + @to.register(TimestampNanoType) |
| 545 | + def _(self, _: TimestampNanoType) -> Literal[int]: |
| 546 | + return self |
| 547 | + |
| 548 | + @to.register(TimestamptzNanoType) |
| 549 | + def _(self, _: TimestamptzNanoType) -> Literal[int]: |
| 550 | + return self |
| 551 | + |
| 552 | + @to.register(TimestampType) |
| 553 | + def _(self, _: TimestampType) -> Literal[int]: |
| 554 | + return TimestampLiteral(nanos_to_micros(self.value)) |
| 555 | + |
| 556 | + @to.register(TimestamptzType) |
| 557 | + def _(self, _: TimestamptzType) -> Literal[int]: |
| 558 | + return TimestampLiteral(nanos_to_micros(self.value)) |
| 559 | + |
| 560 | + @to.register(DateType) |
| 561 | + def _(self, _: DateType) -> Literal[int]: |
| 562 | + return DateLiteral(nanos_to_days(self.value)) |
| 563 | + |
498 | 564 |
|
499 | 565 | class DecimalLiteral(Literal[Decimal]): |
500 | 566 | def __init__(self, value: Decimal) -> None: |
@@ -615,6 +681,14 @@ def _(self, _: TimestampType) -> Literal[int]: |
615 | 681 | def _(self, _: TimestamptzType) -> Literal[int]: |
616 | 682 | return TimestampLiteral(timestamptz_to_micros(self.value)) |
617 | 683 |
|
| 684 | + @to.register(TimestampNanoType) |
| 685 | + def _(self, _: TimestampNanoType) -> Literal[int]: |
| 686 | + return TimestampNanoLiteral(timestamp_to_nanos(self.value)) |
| 687 | + |
| 688 | + @to.register(TimestamptzNanoType) |
| 689 | + def _(self, _: TimestamptzNanoType) -> Literal[int]: |
| 690 | + return TimestampNanoLiteral(timestamptz_to_nanos(self.value)) |
| 691 | + |
618 | 692 | @to.register(UUIDType) |
619 | 693 | def _(self, _: UUIDType) -> Literal[bytes]: |
620 | 694 | return UUIDLiteral(UUID(self.value).bytes) |
|
0 commit comments