Skip to content

Conversation

@isaacharrisholt
Copy link

@isaacharrisholt isaacharrisholt commented Dec 3, 2025

Adds a new interpolation macro called timestamp_to_datetime which is essentially the reverse of the existing timestamp macro, taking an integers timestamp and converting it to a datetime object.

The motivation for this is working with the Xero API, which uses the C#.NET format for dates (e.g. /Date(1764104832903+0000)/). Currently we have no way of transforming this to an ISO date in the Connector Builder, which is something we need to do to enable incremental syncing.

Would greatly appreciate this feature!

Summary by CodeRabbit

  • New Features

    • Added a macro to convert Unix timestamps (int, float, or numeric string) into UTC-aware datetimes.
  • Tests

    • Added comprehensive tests covering valid inputs for multiple types and invalid-input error handling, and registered the macro in the macro export checks.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

📝 Walkthrough

Walkthrough

A new macro function timestamp_to_datetime was added to convert Unix timestamps (int, float, or numeric string) to UTC datetime objects with input validation and was exported in the macros registry; tests were added to cover valid and invalid inputs.

Changes

Cohort / File(s) Summary
Macro Implementation
airbyte_cdk/sources/declarative/interpolation/macros.py
Added timestamp_to_datetime(ts: Union[int, float, str]) -> datetime.datetime with input validation; included in _macros_list and exposed via public macros mapping.
Test Coverage
unit_tests/sources/declarative/interpolation/test_macros.py
Added parametrized tests for int, float, and numeric-string inputs producing UTC datetimes; added test asserting ValueError for invalid input; registered macro in export checks.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Pay attention to handling of sub-second vs. second units and very large/negative timestamps — should we add explicit millisecond vs. second disambiguation or documentation for expected units? wdyt?
  • Confirm timezone is tz-aware UTC across conversions and tests.

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • natikgadzhi
  • darynaishchenko
  • maxi297

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a new timestamp_to_datetime macro to the codebase.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
airbyte_cdk/sources/declarative/interpolation/macros.py (1)

74-89: Nice implementation! Consider using datetime.timezone.utc for consistency?

The function logic is solid and the error handling is appropriate. However, I noticed that now_utc() (line 32) uses datetime.timezone.utc while this new function uses pytz.utc. For consistency and alignment with modern Python standards (where datetime.timezone.utc is the preferred built-in), would you consider switching to datetime.timezone.utc? The tests already expect datetime.timezone.utc in their assertions, though the comparison should work either way.

-    return datetime.datetime.fromtimestamp(ts_value, tz=pytz.utc)
+    return datetime.datetime.fromtimestamp(ts_value, tz=datetime.timezone.utc)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between daf7d48 and 383ebb3.

📒 Files selected for processing (2)
  • airbyte_cdk/sources/declarative/interpolation/macros.py (2 hunks)
  • unit_tests/sources/declarative/interpolation/test_macros.py (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Check: source-intercom
  • GitHub Check: Manifest Server Docker Image Build
  • GitHub Check: SDM Docker Image Build
  • GitHub Check: Pytest (All, Python 3.12, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.13, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.10, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.11, Ubuntu)
  • GitHub Check: Pytest (Fast)
🔇 Additional comments (4)
airbyte_cdk/sources/declarative/interpolation/macros.py (1)

243-243: LGTM!

The function is correctly registered in the macros list and will be exported properly.

unit_tests/sources/declarative/interpolation/test_macros.py (3)

18-18: LGTM!

The new macro is correctly registered in the export test.


180-203: Excellent test coverage!

The parametrized tests cover the key input types (int, float, string) and correctly validate the microsecond handling for float inputs. The test structure follows the existing patterns in the file nicely.


206-209: LGTM!

Good error handling test that validates the ValueError is raised for invalid inputs.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 383ebb3 and 95bebbd.

📒 Files selected for processing (1)
  • airbyte_cdk/sources/declarative/interpolation/macros.py (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Pytest (Fast)
  • GitHub Check: Pytest (All, Python 3.11, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.12, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.10, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.13, Ubuntu)
  • GitHub Check: Manifest Server Docker Image Build
  • GitHub Check: SDM Docker Image Build
🔇 Additional comments (1)
airbyte_cdk/sources/declarative/interpolation/macros.py (1)

239-254: Macro registration in _macros_list looks consistent

Registering timestamp_to_datetime right after timestamp in _macros_list keeps the public macros namespace coherent and should make this immediately usable from Jinja, which looks good to me. I don’t see any further changes needed here.

Comment on lines +74 to +90
def timestamp_to_datetime(ts: Union[int, float, str]) -> datetime.datetime:
"""
Converts a Unix timestamp to a datetime object with UTC timezone.
Usage:
"{{ timestamp_to_datetime(1658505815) }}"
:param ts: Unix timestamp (in seconds) to convert to datetime
:return: datetime object in UTC timezone
"""
try:
ts_value = float(ts)
except (TypeError, ValueError) as exc:
raise ValueError(f"Invalid timestamp value: {ts}") from exc

return datetime.datetime.fromtimestamp(ts_value, tz=datetime.timezone.utc)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Document timestamp_to_datetime behavior for Xero millisecond timestamps; consider exception wrapping

The function explicitly documents "Unix timestamp (in seconds)" and passes float(ts) to datetime.fromtimestamp. However, the Xero C#.NET format /Date(1764104832903+0000)/ contains milliseconds. If a connector author extracts 1764104832903 from Xero data and passes it directly here, they'll get an OverflowError instead of a clear, actionable error message.

Consider one of these approaches:

  • Explicit seconds-only: Enhance the docstring and add a clear example showing how to convert Xero milliseconds to seconds before calling this macro (e.g., divide by 1000), or
  • Auto-detect milliseconds: Detect and handle millisecond inputs (e.g., by checking if the value exceeds a reasonable seconds threshold and dividing by 1000), though this introduces ambiguity for legitimate large timestamps.

As a follow-up polish (optional), consider wrapping datetime.fromtimestamp's potential OverflowError and OSError in ValueError to provide a consistent exception contract, similar to your float(ts) handling.

🤖 Prompt for AI Agents
airbyte_cdk/sources/declarative/interpolation/macros.py around lines 74-90: The
timestamp_to_datetime docstring and implementation assume seconds but callers
(e.g., Xero) may pass millisecond values causing OverflowError; update the
docstring to clearly state the function expects seconds and give an example
showing dividing milliseconds by 1000, and modify the implementation to either
(preferred) detect millisecond inputs (if ts numeric and > 10**11 treat as ms
and divide by 1000) or (alternative) leave behavior unchanged but add an
explicit check that raises a ValueError with a clear message if the numeric
value is unreasonably large; also wrap datetime.fromtimestamp calls in
try/except to catch OverflowError and OSError and re-raise as ValueError with a
descriptive message including the original value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant