Skip to content

enhancement(util): accept nanos and timestamps without Z/z in timestamp conversion#268

Open
HassanBahati wants to merge 2 commits into@invertase/robustify-timestamp-conversionfrom
fix/util-timestamp-nanos-and-no-timezone-suffix
Open

enhancement(util): accept nanos and timestamps without Z/z in timestamp conversion#268
HassanBahati wants to merge 2 commits into@invertase/robustify-timestamp-conversionfrom
fix/util-timestamp-nanos-and-no-timezone-suffix

Conversation

@HassanBahati
Copy link
Member

@HassanBahati HassanBahati commented Feb 10, 2026

Description

This PR extends the timestamp conversion fixes in #262 so the SDK accepts payloads without requiring callers to normalize them:

  • dict/object timestamps may use the nanos key/attribute (protobuf-style) in addition to nanoseconds;
  • string timestamps whose fractional part has no timezone suffix (e.g. "2025-11-06T12:00:00.000") no longer cause ValueError in get_precision_timestamp. The same integer-based normalization (divmod, timedelta) and review feedback from PR fix(util): improve the robustness of timestamp conversion function #262 are preserved.

Related Issues

Fixes #260 (fully; PR #262 fixed the dict/object path for nanoseconds only; this adds nanos and fixes the string path when Z/z is missing).

Changes Made

  • timestamp_conversion (util.py):
    • Object branch: Resolve sub-second value via getattr(timestamp, "nanoseconds", getattr(timestamp, "nanos", None)) so both .nanoseconds and .nanos are accepted.
    • Dict branch: Resolve via timestamp.get("nanoseconds", timestamp.get("nanos")) so both "nanoseconds" and "nanos" keys are accepted (e.g. protobuf/Firebase backend payloads).
  • get_precision_timestamp (util.py): Only split the fraction on "Z" or "z" when present; otherwise use the fraction as-is. Prevents ValueError: not enough values to unpack when the Cloud Event time (or other string) has no trailing timezone (e.g. "2025-11-06T12:00:00.000").
  • Tests (test_util.py):
    • test_timestamp_conversion_dict_nanos_equivalent_to_nanoseconds: dict with "nanos" produces the same result as "nanoseconds".
    • test_timestamp_conversion_object_nanos: object with .seconds and .nanos (no .nanoseconds) is accepted and matches dict result.
    • test_get_precision_timestamp_without_timezone_suffix: get_precision_timestamp("2025-11-06T12:00:00.000") does not raise and returns MICROSECONDS.

Testing

Tests Run

  • Unit tests
    • pytest tests/test_util.py -v -k "timestamp_conversion or get_precision"
  • Integration tests
  • Manual testing
    • Built the package and installed it into the issue-260 MRE. Started Firebase Functions emulator, sent POST with payloads/stability_digest_ce.json (payload uses digestDate with nanos and includes top-level time). Result: handler ran successfully, log showed Stability digest: app_id=1:123456789:android:abcdef, curl returned OK. No AttributeError or ValueError.

Additional Notes

  • Enhancement over PR fix(util): improve the robustness of timestamp conversion function #262: PR fix(util): improve the robustness of timestamp conversion function #262 added handling for dict/object timestamps with "seconds" and "nanoseconds" and kept the existing string path. This PR; widens accepted keys/attributes to include nanos, and (2) fixes the string path in get_precision_timestamp when the fraction has no Z/z. Same normalization logic and alignment with review (no fromtimestamp, integer math, docstring/parameter names) are unchanged.
  • What was happening before: With PR fix(util): improve the robustness of timestamp conversion function #262, payloads where the backend sends digestDate as {"seconds": "...", "nanos": 0} still failed (dict branch required "nanoseconds"). After accommodating that, the event’s top-level time field could be a string without a trailing Z/z; get_precision_timestamp then did s_fraction.split("z") and unpacked to two values, causing ValueError: not enough values to unpack (expected 2, got 1). This PR addresses both cases so the SDK accepts varied real-world payloads.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @HassanBahati, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the robustness of timestamp conversion utilities within the SDK. It addresses previous limitations by allowing more flexible input formats for timestamps, specifically by accepting both nanos and nanoseconds attributes/keys in structured timestamp objects and dictionaries, and by gracefully handling string-based timestamps that omit a timezone suffix. These changes ensure broader compatibility with various backend payloads and prevent common parsing errors, making the SDK more resilient to diverse data representations.

Highlights

  • Enhanced Timestamp Conversion: The timestamp_conversion function now accepts nanos as an alternative to nanoseconds for both object and dictionary timestamp inputs, improving compatibility with protobuf-style payloads.
  • Robust String Timestamp Parsing: The get_precision_timestamp function was updated to correctly parse string timestamps that do not include a 'Z' or 'z' timezone suffix, preventing ValueError for such inputs.
  • Comprehensive Unit Tests: New unit tests were added to validate the extended timestamp_conversion logic for nanos and the improved get_precision_timestamp handling of strings without timezone suffixes.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/firebase_functions/private/util.py
    • Modified get_precision_timestamp to handle string timestamps without 'Z' or 'z' timezone suffixes.
    • Updated timestamp_conversion to recognize both 'nanoseconds' and 'nanos' for sub-second values in object and dictionary inputs.
  • tests/test_util.py
    • Added a test case to confirm timestamp_conversion correctly processes dictionaries using 'nanos'.
    • Added a test case to confirm timestamp_conversion correctly processes objects using 'nanos'.
    • Added a test case to confirm get_precision_timestamp handles string timestamps lacking a timezone suffix.
Activity
  • No specific activity (comments, reviews, or progress updates) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@HassanBahati HassanBahati requested a review from cabljac February 10, 2026 09:56
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request enhances the timestamp conversion utility by allowing nanos as an alternative to nanoseconds in object and dictionary representations, and by correctly handling string timestamps that lack a 'Z' or 'z' timezone suffix. The changes are well-tested with new unit tests covering these specific scenarios. The overall functionality is improved, making the utility more robust to varied input formats.

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
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.

2 participants