Skip to content

fix: standardize libSQL timestamps as RFC 3339 UTC#683

Open
tsubasakong wants to merge 3 commits intonearai:mainfrom
tsubasakong:fix/663-libsql-rfc3339-timestamps
Open

fix: standardize libSQL timestamps as RFC 3339 UTC#683
tsubasakong wants to merge 3 commits intonearai:mainfrom
tsubasakong:fix/663-libsql-rfc3339-timestamps

Conversation

@tsubasakong
Copy link

Summary

  • replace libSQL datetime(now) defaults/usages in migrations with RFC 3339 UTC strftime(...) values\n- keep legacy naive timestamp parsing for backward compatibility, but warn when that fallback is used\n- add focused timestamp parsing/format coverage for the canonical libSQL timestamp format\n\nFixes Standardize libSQL timestamp storage to RFC 3339 with UTC offset #663\n\n## Validation\n- git diff --check\n- verified src/db/libsql_migrations.rs no longer contains datetime(now)\n- added unit coverage for RFC 3339 + legacy naive timestamp parsing paths\n\n## Notes\n- supersedes fix: standardize libSQL timestamps as RFC 3339 UTC #680, which appears to have been closed with a reason intended for a different PR\n- Rust toolchain is not installed on this host, so I could not run cargo test locally; CI will perform the full compile/test pass.

@github-actions github-actions bot added scope: db/libsql libSQL / Turso backend size: M 50-199 changed lines risk: medium Business logic, config, or moderate-risk modules labels Mar 7, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, 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 enhances the robustness and consistency of timestamp handling within the libSQL database layer. It transitions the default timestamp generation in all database migrations to the explicit RFC 3339 UTC format, which eliminates ambiguity and improves data integrity. To ensure a smooth transition, the system now logs warnings when encountering older, naive timestamp formats, while still correctly parsing them for backward compatibility. These changes are supported by new, focused unit tests that validate the correct parsing and formatting of both new and legacy timestamp types.

Highlights

  • Timestamp Standardization: Standardized the generation of timestamps in libSQL migrations to use the RFC 3339 UTC format, replacing the less precise datetime(now).
  • Backward Compatibility: Implemented warnings when parsing legacy naive timestamps, ensuring existing data remains compatible while signaling the use of a deprecated format.
  • Improved Test Coverage: Added new unit tests to specifically cover both the canonical RFC 3339 timestamp format and the legacy naive timestamp parsing paths.
Changelog
  • src/db/libsql/mod.rs
    • Added tracing::warn! calls to parse_timestamp when processing naive timestamps, indicating that UTC is assumed for backward compatibility.
    • Introduced test_parse_timestamp_accepts_rfc3339_and_legacy_naive_formats to verify correct parsing of various timestamp formats.
    • Added test_libsql_now_format_is_rfc3339_and_parseable to confirm that strftime('%Y-%m-%dT%H:%M:%fZ', 'now') generates a parsable RFC 3339 timestamp.
  • src/db/libsql_migrations.rs
    • Replaced datetime('now') with strftime('%Y-%m-%dT%H:%M:%fZ', 'now') in DEFAULT clauses for timestamp columns across all relevant tables in the schema.
    • Updated the update_memory_documents_updated_at trigger to use the new strftime format for updated_at.
    • Modified INSERT OR IGNORE statements for leak_detection_patterns to use the standardized strftime format for created_at.
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.

@github-actions github-actions bot added the contributor: new First-time contributor label Mar 7, 2026
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 standardizes libSQL timestamps to RFC 3339 UTC format, which is a great improvement for consistency. The changes involve updating all datetime('now') calls in migrations to use strftime for the new format. I appreciate that you've maintained backward compatibility for parsing legacy naive timestamps and added warnings to guide users towards the new format. The new tests provide good coverage for these changes.

I have a couple of suggestions to improve the maintainability and robustness of the code. One is to refactor a small piece of duplicated code in the timestamp parsing logic for conciseness. The others are to use a more explicit and readable format for generating timestamps in SQL, both in the migrations and in the related test query, to avoid relying on potentially fragile SQLite behavior and make the intent clearer to future developers.

Comment on lines 171 to 185
if let Ok(ndt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S%.f") {
tracing::warn!(
timestamp = %s,
"parsed naive timestamp without timezone; assuming UTC for backward compatibility"
);
return Ok(ndt.and_utc());
}
// Naive without fractional seconds (legacy format)
if let Ok(ndt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
tracing::warn!(
timestamp = %s,
"parsed naive timestamp without timezone; assuming UTC for backward compatibility"
);
return Ok(ndt.and_utc());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There's some code duplication in the handling of legacy naive timestamp formats. You can combine these two if let blocks into one by chaining the parsing attempts with or_else. This will make the code more concise and easier to maintain.

    if let Ok(ndt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S%.f")
        .or_else(|_| NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S"))
    {
        tracing::warn!(
            timestamp = %s,
            "parsed naive timestamp without timezone; assuming UTC for backward compatibility"
        );
        return Ok(ndt.and_utc());
    }

let conn = backend.connect().await.unwrap();
let mut rows = conn
.query(
"SELECT strftime('%Y-%m-%dT%H:%M:%fZ', 'now')",
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

To align with the suggestion for more explicit timestamp formatting in the migrations file, this test query should also be updated. Using a more verbose but clearer construction for generating the RFC 3339 timestamp will improve maintainability.

                "SELECT strftime('%Y-%m-%dT%H:%M:%S', 'now') || '.' || substr(strftime('%f', 'now'), 4) || 'Z'",

version INTEGER PRIMARY KEY,
name TEXT NOT NULL,
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
applied_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The format string '%Y-%m-%dT%H:%M:%fZ' is a bit confusing as it relies on a non-standard and sparsely documented quirk of SQLite's strftime where %f seems to imply seconds plus fractional seconds. For better readability and to avoid relying on this potentially fragile behavior, consider using a more explicit construction. This would make the intent clearer to future maintainers. This comment applies to all similar strftime calls in this file.

Suggested change
applied_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
applied_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%S', 'now') || '.' || substr(strftime('%f', 'now'), 4) || 'Z')

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

Labels

contributor: new First-time contributor risk: medium Business logic, config, or moderate-risk modules scope: db/libsql libSQL / Turso backend size: M 50-199 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant