Skip to content

fix: allow timezone-aware datetime in Block schema#63

Closed
kuu13580 wants to merge 1 commit intodevelopfrom
fix-block-schema-timezone-12752935626976310622
Closed

fix: allow timezone-aware datetime in Block schema#63
kuu13580 wants to merge 1 commit intodevelopfrom
fix-block-schema-timezone-12752935626976310622

Conversation

@kuu13580
Copy link
Contributor

@kuu13580 kuu13580 commented Feb 8, 2026

This PR fixes an issue where sending timezone-aware datetimes (e.g. "2023-01-01T10:00:00Z") to the block creation/update endpoints would cause a database error because the column is TIMESTAMP WITHOUT TIME ZONE.

I added a Pydantic field_validator to BlockBase that detects aware datetimes, converts them to UTC, and strips the timezone info to make them naive. This ensures consistent UTC storage in the database regardless of input format.

I also added a new test file server/tests/schemas/test_block.py covering various scenarios.


PR created automatically by Jules for task 12752935626976310622 started by @kuu13580

This change adds a validator to the `Block` schema to handle timezone-aware datetimes.
It converts any aware datetime to UTC and then makes it naive, which is required by the `TIMESTAMP WITHOUT TIME ZONE` column in the database.
This allows the API to accept ISO 8601 strings with 'Z' or other offsets, while maintaining compatibility with the existing naive datetime behavior.

- Modified `server/app/schemas/block.py` to add `validate_timezone` validator.
- Added `server/tests/schemas/test_block.py` to test the validator.

Co-authored-by: kuu13580 <46004336+kuu13580@users.noreply.github.com>
@google-labs-jules
Copy link

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@gemini-code-assist
Copy link

Summary of Changes

Hello @kuu13580, 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 resolves a critical issue where sending timezone-aware datetimes to block creation/update endpoints would result in a database error due to the TIMESTAMP WITHOUT TIME ZONE column type. The solution standardizes datetime storage by automatically converting all incoming timezone-aware datetimes to naive UTC, thereby preventing data integrity problems and ensuring consistent time representation within the system.

Highlights

  • Timezone Handling: Implemented a Pydantic field_validator in BlockBase to correctly handle timezone-aware datetimes for start_time and end_time fields.
  • Data Consistency: The validator converts any timezone-aware datetime input to UTC and then strips the timezone information, ensuring all datetimes are stored as consistent, naive UTC values in the database.
  • New Test Coverage: Added a new test file, server/tests/schemas/test_block.py, to validate the timezone conversion logic across various scenarios, including naive, UTC-aware, and offset-aware inputs.

🧠 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
  • server/app/schemas/block.py
    • Imported timezone from datetime and field_validator from pydantic.
    • Added a field_validator named validate_timezone to BlockBase for start_time and end_time.
    • The validator checks if a datetime is timezone-aware; if so, it converts it to UTC and removes timezone information, making it naive.
  • server/tests/schemas/test_block.py
    • New test file added to validate the BlockBase schema's datetime handling.
    • Includes tests for naive datetime inputs, ensuring they remain unchanged.
    • Contains tests for UTC-aware datetime inputs, verifying conversion to naive UTC.
    • Features tests for offset-aware datetime inputs, confirming correct conversion to naive UTC.
    • Adds a test case to ensure optional end_time fields are handled correctly.
Activity
  • The pull request was automatically created by Jules for a task initiated by @kuu13580.
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
Copy link

github-actions bot commented Feb 8, 2026

Visit the preview URL for this PR (updated for commit 7d6fe8e):

https://tabi-share-8ef6b--pr63-fix-block-schema-tim-l0devlsj.web.app

(expires Sun, 15 Feb 2026 02:21:40 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 9f2a87ede127df7673322845e34cf22c1372d720

Copy link

@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

このプルリクエストは、タイムゾーンを持つdatetimeが送信された場合に発生するデータベースエラーを修正するものです。Pydanticのfield_validatorを使用して、タイムゾーン付きの日時をUTCに変換し、タイムゾーン情報を削除してnaiveなdatetimeとしてデータベースに保存するアプローチは適切です。また、この変更を検証するためのテストケースが追加されている点も素晴らしいです。スタイルガイドに従い、日本語でレビューします。1点、テストコードの保守性を向上させるための提案をさせていただきました。

Comment on lines +1 to +49
from datetime import datetime, timezone
from app.schemas.block import BlockCreate, BlockType

def test_timezone_naive_input():
# Naive string: 2023-01-01T10:00:00
data = {
"title": "Naive",
"start_time": "2023-01-01T10:00:00",
"end_time": "2023-01-01T12:00:00",
"detail": "detail",
"block_type": "event",
}
block = BlockCreate(**data)
assert block.start_time.tzinfo is None
assert block.start_time == datetime(2023, 1, 1, 10, 0, 0)
assert block.end_time.tzinfo is None
assert block.end_time == datetime(2023, 1, 1, 12, 0, 0)

def test_timezone_aware_utc_input():
# Aware UTC string: 2023-01-01T10:00:00Z
data = {
"title": "Aware UTC",
"start_time": "2023-01-01T10:00:00Z",
"end_time": "2023-01-01T12:00:00Z",
"detail": "detail",
"block_type": "event",
}
block = BlockCreate(**data)
# Pydantic parses Z as UTC aware. The validator should convert to naive UTC.
assert block.start_time.tzinfo is None
assert block.start_time == datetime(2023, 1, 1, 10, 0, 0)
assert block.end_time.tzinfo is None
assert block.end_time == datetime(2023, 1, 1, 12, 0, 0)

def test_timezone_aware_offset_input():
# Aware Offset string: 2023-01-01T19:00:00+09:00 (JST) -> 10:00 UTC
data = {
"title": "Aware Offset",
"start_time": "2023-01-01T19:00:00+09:00",
"end_time": "2023-01-01T21:00:00+09:00",
"detail": "detail",
"block_type": "event",
}
block = BlockCreate(**data)
# The validator should convert to UTC and make naive.
assert block.start_time.tzinfo is None
assert block.start_time == datetime(2023, 1, 1, 10, 0, 0)
assert block.end_time.tzinfo is None
assert block.end_time == datetime(2023, 1, 1, 12, 0, 0)

Choose a reason for hiding this comment

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

medium

3つのテストケース(test_timezone_naive_input, test_timezone_aware_utc_input, test_timezone_aware_offset_input)は、テストロジックがほぼ同じです。pytest.mark.parametrizeを使用することで、これらのテストを1つのパラメータ化されたテストにまとめることができます。これにより、コードの重複が減り、保守性が向上します。これは、スタイルガイドの「保守性」と「一貫性」の原則にも合致します。

提案コードでは、3つのテストを1つにまとめ、関連するimport文も整理しています。

import pytest
from datetime import datetime
from app.schemas.block import BlockCreate


@pytest.mark.parametrize(
    ("test_id", "start_time_in", "end_time_in", "expected_start", "expected_end"),
    [
        (
            "naive",
            "2023-01-01T10:00:00",
            "2023-01-01T12:00:00",
            datetime(2023, 1, 1, 10, 0, 0),
            datetime(2023, 1, 1, 12, 0, 0),
        ),
        (
            "aware_utc",
            "2023-01-01T10:00:00Z",
            "2023-01-01T12:00:00Z",
            datetime(2023, 1, 1, 10, 0, 0),
            datetime(2023, 1, 1, 12, 0, 0),
        ),
        (
            "aware_offset",
            "2023-01-01T19:00:00+09:00",
            "2023-01-01T21:00:00+09:00",
            datetime(2023, 1, 1, 10, 0, 0),
            datetime(2023, 1, 1, 12, 0, 0),
        ),
    ],
)
def test_datetime_validation(test_id, start_time_in, end_time_in, expected_start, expected_end):
    """Datetime validation should handle naive, UTC, and offset-aware inputs."""
    data = {
        "title": f"Test {test_id}",
        "start_time": start_time_in,
        "end_time": end_time_in,
        "detail": "detail",
        "block_type": "event",
    }
    block = BlockCreate(**data)
    assert block.start_time.tzinfo is None
    assert block.start_time == expected_start
    assert block.end_time.tzinfo is None
    assert block.end_time == expected_end
References
  1. コードは、将来の修正や機能拡張が容易に行えるように設計します (保守性: 9行目) (link)
  2. すべてのプロジェクトで一貫したスタイルを保つことで、共同作業を円滑にし、エラーを削減します (一貫性: 10行目) (link)

@kuu13580 kuu13580 closed this Feb 11, 2026
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

Comments