Skip to content

feat: Add XsdDate type and codec for XSD-compliant date handling.#75

Merged
mark-dropbear merged 1 commit intomainfrom
date
Nov 27, 2025
Merged

feat: Add XsdDate type and codec for XSD-compliant date handling.#75
mark-dropbear merged 1 commit intomainfrom
date

Conversation

@mark-dropbear
Copy link
Contributor

No description provided.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @mark-dropbear, 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 library's XSD datatype support by introducing a dedicated XsdDate type and its associated XsdDateCodec. This new feature provides a robust and compliant mechanism for handling xsd:date values, ensuring accurate parsing, validation, and serialization of dates, whether they are floating, UTC, or include a timezone offset. This addition expands the library's capabilities for working with XML Schema Definition dates.

Highlights

  • New XsdDate Type: Introduced a new XsdDate class for handling XSD-compliant date values, wrapping DateTime and ensuring time components are zeroed out.
  • XsdDateCodec Implementation: Added a Codec for XsdDate to facilitate conversion between XsdDate objects and their XSD string representations, including robust parsing and serialization.
  • Comprehensive Date Handling: The XsdDate type supports floating dates, UTC dates, and dates with timezone offsets, providing flexibility and accuracy in XSD date interpretation.
  • Strict Validation: Implemented strict validation during parsing to ensure that date components (year, month, day) are valid according to XSD rules, preventing incorrect date representations.
  • Documentation and Testing: Updated CHANGELOG.md and README.md to reflect the new feature, and added dedicated unit tests for both XsdDate and XsdDateCodec to ensure correctness and reliability.
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.

@mark-dropbear mark-dropbear merged commit f97d9fa into main Nov 27, 2025
1 check passed
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 introduces a new XsdDate type and its corresponding codec, which is a great addition for XSD compliance. The implementation is solid and well-tested. I've found one high-severity issue regarding missing validation for timezone offset ranges in the XsdDate.parse method, which could lead to accepting invalid date strings. I've provided a detailed comment with a code suggestion to fix this and improve the clarity of the parsing logic. I've also suggested adding a few more test cases to cover this scenario and prevent future regressions. Overall, great work on this feature.

Comment on lines +70 to +81
Duration? offset;
if (tzStr == 'Z') {
offset = Duration.zero;
} else {
final tzMatch = _offsetRegex.firstMatch(tzStr);
if (tzMatch != null) {
final sign = tzMatch.group(1) == '+' ? 1 : -1;
final hours = int.parse(tzMatch.group(2)!);
final minutes = int.parse(tzMatch.group(3)!);
offset = Duration(hours: hours, minutes: minutes) * sign;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The logic for parsing the timezone can be improved for clarity and correctness.

  1. Correctness: The current implementation does not validate the range of the timezone offset. According to the XSD 1.1 specification, the offset hh must be between 00-14 and mm between 00-59 (with mm being 00 if hh is 14). An invalid offset like +15:00 would be incorrectly parsed.
  2. Clarity: Since _dateRegex ensures that tzStr (if not null and not 'Z') will be in the [+-]HH:mm format, the _offsetRegex will always find a match. The null check on tzMatch is redundant.

The suggested change addresses both points by adding the validation and simplifying the logic.

      final Duration offset;
      if (tzStr == 'Z') {
        offset = Duration.zero;
      } else {
        // _dateRegex ensures tzStr is in [+-]HH:mm format, so a match is guaranteed.
        final tzMatch = _offsetRegex.firstMatch(tzStr)!;
        final sign = tzMatch.group(1) == '+' ? 1 : -1;
        final hours = int.parse(tzMatch.group(2)!);
        final minutes = int.parse(tzMatch.group(3)!);
        if (hours > 14 || minutes > 59 || (hours == 14 && minutes != 0)) {
          throw FormatException('Invalid timezone offset range', input);
        }
        offset = Duration(hours: hours, minutes: minutes) * sign;
      }

() => XsdDate.parse('2002-02-30'),
throwsFormatException,
); // Invalid day
});
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 test group is great for format validation! To make it even more robust, could you also add test cases for invalid timezone offsets? This will help prevent future regressions for the timezone validation logic you're adding.

For example:

      expect(
        () => XsdDate.parse('2002-10-10+15:00'), // Hour > 14
        throwsFormatException,
      );
      expect(
        () => XsdDate.parse('2002-10-10-14:01'), // Minute > 00 when hour is 14
        throwsFormatException,
      );

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