Skip to content

NIFI-15900 Add optional timezone to plusDuration and minusDuration for DST-aware calendar arithmetic#11296

Merged
pvillard31 merged 1 commit into
apache:mainfrom
rakesh-rsky:fix/NIFI-15900-dst-aware-plusDuration
Jun 2, 2026
Merged

NIFI-15900 Add optional timezone to plusDuration and minusDuration for DST-aware calendar arithmetic#11296
pvillard31 merged 1 commit into
apache:mainfrom
rakesh-rsky:fix/NIFI-15900-dst-aware-plusDuration

Conversation

@rakesh-rsky
Copy link
Copy Markdown
Contributor

NIFI-15900 Add optional timezone to plusDuration and minusDuration for DST-aware calendar arithmetic

When adding or subtracting calendar units (days, weeks, months, years) across DST boundaries, the result should preserve the wall-clock time rather than adding a fixed number of seconds. Previously, both functions always used the JVM system default timezone when converting the Date to a ZonedDateTime, which produced incorrect results when the desired timezone differed from the system default.

Changes:

  • Add optional timezone parameter to plusDuration and minusDuration functions e.g. plusDuration('1 day', 'America/New_York')
  • Update ANTLR parser grammar to allow 1 or 2 arguments for these functions
  • AbstractDateArithmeticEvaluator uses the provided timezone (or system default) when performing calendar arithmetic
  • Add DST boundary test cases covering spring-forward and fall-back scenarios

Summary

NIFI-15900

Tracking

Please complete the following tracking steps prior to pull request creation.

Issue Tracking

Pull Request Tracking

  • Pull Request title starts with Apache NiFi Jira issue number, such as NIFI-00000
  • Pull Request commit message starts with Apache NiFi Jira issue number, as such NIFI-00000
  • Pull request contains commits signed with a registered key indicating Verified status

Pull Request Formatting

  • Pull Request based on current revision of the main branch
  • Pull Request refers to a feature branch with one commit containing changes

Verification

Please indicate the verification steps performed prior to pull request creation.

Build

  • Build completed using ./mvnw clean install -P contrib-check
    • JDK 21
    • JDK 25

Licensing

  • New dependencies are compatible with the Apache License 2.0 according to the License Policy
  • New dependencies are documented in applicable LICENSE and NOTICE files

Documentation

  • Documentation formatting appears as expected in rendered files

Copy link
Copy Markdown
Contributor

@pvillard31 pvillard31 left a comment

Choose a reason for hiding this comment

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

Please rebase on top of main before submitting a PR so that the GitHub checks can run.

@rakesh-rsky rakesh-rsky force-pushed the fix/NIFI-15900-dst-aware-plusDuration branch from 1cd92a2 to 3dba077 Compare June 1, 2026 17:41
@rakesh-rsky rakesh-rsky requested a review from pvillard31 June 1, 2026 17:43
* <pre>
* ${date:toDate('dd-MM-yyyy'):plusDuration('1 week'):format('dd-MM-yyyy')}
* ${date:toDate('dd-MM-yyyy'):plusDuration('2 years')}
* ${date:toDate('dd-MM-yyyy', 'America/Chicago'):plusDuration('1 day', 'America/Chicago'):format('dd-MM-yyyy', 'America/Chicago')}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The expression language guide documents plusDuration and minusDuration with only the amount argument. Should we update expression-language-guide.adoc to document the new optional timezone argument and add a DST example?

if (timeZoneEvaluator != null) {
final String tz = timeZoneEvaluator.evaluate(evaluationContext).getValue();
if (tz != null) {
zoneId = ZoneId.of(tz);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The amount literal is validated in the constructor, but the timezone is only resolved at evaluate time. Should we validate a literal timezone at construction so an invalid zone fails fast like an invalid amount?

…r DST-aware calendar arithmetic

When adding or subtracting calendar units (days, weeks, months, years) across DST
boundaries, the result should preserve the wall-clock time rather than adding a
fixed number of seconds. Previously, both functions always used the JVM system
default timezone when converting the Date to a ZonedDateTime, which produced
incorrect results when the desired timezone differed from the system default.

Changes:
- Add optional timezone parameter to plusDuration and minusDuration functions
  e.g. plusDuration('1 day', 'America/New_York')
- Update ANTLR parser grammar to allow 1 or 2 arguments for these functions
- AbstractDateArithmeticEvaluator uses the provided timezone (or system default)
  when performing calendar arithmetic
- Add DST boundary test cases covering spring-forward and fall-back scenarios
@rakesh-rsky rakesh-rsky force-pushed the fix/NIFI-15900-dst-aware-plusDuration branch from 3dba077 to 23214dc Compare June 2, 2026 17:32
@rakesh-rsky
Copy link
Copy Markdown
Contributor Author

@pvillard31 you are right I have updated expression-language-guide.adoc for both plusDuration and minusDuration to document the new optional timezone argument, added a DST example row to each example table, and added a DST boundary scenario to each Calendar-Aware Behavior table.

Also added fail-fast validation for literal timezone arguments in the constructor of AbstractDateArithmeticEvaluator, mirroring the existing pattern used for the amount literal via DateAmountParser.validate. For dynamic (non-literal) timezone expressions, the ZoneId.of() call in evaluate() is now also wrapped to throw AttributeExpressionLanguageException consistently. Added test coverage for both cases in TestQuery.

Copy link
Copy Markdown
Contributor

@pvillard31 pvillard31 left a comment

Choose a reason for hiding this comment

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

Thanks, latest LGTM, merging

@pvillard31 pvillard31 merged commit d501315 into apache:main Jun 2, 2026
8 checks passed
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