Skip to content

Fix #274: Use millisecond timestamps for date filtering to fix timezone issue#276

Merged
ding113 merged 1 commit intodevfrom
fix/issue-274-timezone-handling
Dec 6, 2025
Merged

Fix #274: Use millisecond timestamps for date filtering to fix timezone issue#276
ding113 merged 1 commit intodevfrom
fix/issue-274-timezone-handling

Conversation

@ding113
Copy link
Owner

@ding113 ding113 commented Dec 5, 2025

Summary

Fixes the timezone inconsistency issue in usage logs date filtering reported in #274.

Root cause: Date filters were passed as local time strings (e.g., "2025-12-06T00:00") which caused different interpretations between browser and server timezones.

Solution: Use millisecond timestamps (Unix epoch) for frontend-backend communication, eliminating timezone ambiguity.

Changes

  • usage-logs-filters.tsx: Convert selected date ranges to millisecond timestamps
  • usage-logs-view.tsx: Parse/pass timestamps via URL params (startTime/endTime)
  • usage-logs.ts (repository): Accept timestamps and convert to ISO strings for PostgreSQL

Technical Details

Before:

Browser (UTC+8): selects "2025-12-06" → sends "2025-12-06T00:00"
Server (UTC+8): interprets as "2025-12-06 00:00 Asia/Shanghai"
Problem: If browser is in different timezone, wrong data is returned

After:

Browser (UTC+8): selects "2025-12-06" → sends timestamp 1733414400000
Server: converts to ISO "2025-12-05T16:00:00.000Z" → compares with DB
Result: Consistent behavior regardless of browser/server timezone mismatch

Test Plan

  • Select a date range in usage logs filter
  • Verify URL params show startTime and endTime as millisecond timestamps
  • Verify correct records are returned regardless of browser timezone
  • Test at midnight boundary (e.g., Beijing time 00:00-01:00)

Closes #274

🤖 Generated with Claude Code

…sue, close #274

Previously, date filters were passed as local time strings (e.g., "2025-12-06T00:00")
which caused timezone inconsistencies between the browser and server:

- Browser interpreted dates in its local timezone
- Server interpreted the same strings in its configured timezone (TZ env)
- This caused queries to return wrong results when browser/server timezones differed

Changes:
- Frontend now converts selected dates to millisecond timestamps (Unix epoch)
- Backend converts timestamps to ISO strings for PostgreSQL comparison
- URL parameters changed from startDate/endDate to startTime/endTime (ms)
- Removed unused getEnvConfig import from usage-logs repository

This approach eliminates timezone ambiguity by using absolute time points.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ding113, 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 addresses a critical timezone inconsistency bug in the usage logs date filtering mechanism. Previously, date filters were passed as local time strings, leading to misinterpretations across different timezones. The solution involves a comprehensive refactor to use millisecond Unix epoch timestamps for all date-related data transfer, ensuring consistent and accurate filtering regardless of the user's or server's timezone.

Highlights

  • Timezone Inconsistency Fix: Resolved an issue where usage logs date filtering produced inconsistent results due to differing interpretations of local time strings between browser and server timezones.
  • Standardized Timestamps: Implemented the use of millisecond Unix epoch timestamps for all date filtering communication between the frontend and backend, eliminating timezone ambiguity.
  • Frontend Date Handling: Modified usage-logs-filters.tsx to convert selected date ranges into millisecond timestamps and usage-logs-view.tsx to parse and pass these timestamps via URL parameters (startTime/endTime).
  • Backend Date Handling: Updated the usage-logs.ts repository logic to accept millisecond timestamps and convert them to ISO strings for accurate comparison with PostgreSQL's timestamptz type, leveraging PostgreSQL's automatic timezone handling.
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.

@ding113 ding113 added bug Something isn't working size/S Small PR (< 200 lines) labels Dec 5, 2025
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 effectively resolves a timezone inconsistency issue by switching from local time strings to millisecond timestamps for date filtering. The changes across the frontend components and the backend repository are well-implemented and correctly address the root cause. My review includes a couple of suggestions in usage-logs-filters.tsx to improve code maintainability by reducing magic numbers and code duplication when handling dates, recommending more extensive use of the date-fns library.

}, [localFilters.endDateLocal]);
if (!localFilters.endTime) return undefined;
// endTime is next day 00:00, so subtract 1 day to get actual end date
const actualEndDate = new Date(localFilters.endTime - 24 * 60 * 60 * 1000);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Using a magic number for the number of milliseconds in a day (24 * 60 * 60 * 1000) can be fragile, as it doesn't account for edge cases like Daylight Saving Time transitions. It's safer and more readable to use a function from your date library. Since you're already using date-fns, you can use subDays for this. You'll need to import subDays from date-fns.

Suggested change
const actualEndDate = new Date(localFilters.endTime - 24 * 60 * 60 * 1000);
const actualEndDate = subDays(new Date(localFilters.endTime), 1);

Comment on lines +180 to +188
const endTimestamp = new Date(
nextDay.getFullYear(),
nextDay.getMonth(),
nextDay.getDate(),
0,
0,
0,
0
).getTime();
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This block of code manually constructs a Date object to get the start of the day. This logic is already encapsulated in your dateStringToTimestamp helper function. Reusing the helper will make the code more concise and less prone to duplication errors.

        const endTimestamp = dateStringToTimestamp(format(nextDay, "yyyy-MM-dd"));

Copy link
Owner Author

@ding113 ding113 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 Summary

No significant issues identified in this PR. The timezone fix approach is correct - using millisecond timestamps for frontend-backend communication eliminates timezone ambiguity effectively.

PR Size: S

  • Lines changed: 163 (86 additions, 77 deletions)
  • Files changed: 3

Issues Found

Category Critical High Medium Low
Code Quality 0 0 0 0
Security 0 0 0 0
Dependencies - - - -
Documentation - - - -

Review Coverage

  • Code quality and correctness - Clean
  • Security (OWASP Top 10) - Clean
  • PR size assessment - S (appropriate size)
  • Dependency changes - N/A (no dependency changes)
  • Documentation changes - N/A (no docs changes)

Automated review by Claude AI

@ding113 ding113 merged commit f5cbefa into dev Dec 6, 2025
10 checks passed
@github-project-automation github-project-automation bot moved this from Backlog to Done in Claude Code Hub Roadmap Dec 6, 2025
@ding113 ding113 deleted the fix/issue-274-timezone-handling branch December 11, 2025 10:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size/S Small PR (< 200 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant

Comments