Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed duration issue when having multiple time units #350

Merged
merged 4 commits into from
Oct 28, 2024

Conversation

wouterlemcke
Copy link
Contributor

@wouterlemcke wouterlemcke commented Oct 28, 2024

Test speaks for itself I guess. When having multiple units in your duration, the end was not calculated correctly

Summary by CodeRabbit

  • New Features

    • Enhanced handling of event durations in the iCalendar processing, allowing for more robust duration calculations.
  • Bug Fixes

    • Corrected the expected end time in tests to reflect updated event durations, ensuring accuracy in event timing.
  • Tests

    • Refined existing test cases to improve coverage and validate the parsing of various iCalendar files.

@jens-maus
Copy link
Owner

@coderabbitai full review

Copy link

coderabbitai bot commented Oct 28, 2024

✅ Actions performed

Full review triggered.

Copy link

coderabbitai bot commented Oct 28, 2024

Warning

Rate limit exceeded

@jens-maus has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 7 minutes and 48 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Files that changed from the base of the PR and between 2b90200 and 073da3e.

Walkthrough

The changes made in this pull request primarily involve modifications to the ical.js module and its associated test files. In ical.js, the handling of duration in the END function has been enhanced by renaming variables for clarity and implementing a loop to process multiple duration components. The test files have been updated to reflect a corrected expected end time for an event, with adjustments made to the duration in the corresponding .ics file. Overall, the changes focus on improving the accuracy and readability of the duration handling and associated tests.

Changes

File Change Summary
ical.js Updated END function to improve duration handling; renamed newend to newEnd; replaced single regex match with a loop for processing durations. Adjusted logic for setting the end date. Minor comment adjustments.
test/test-async.js Updated expected end time in the test case for test_date_time_duration.ics from 2024-02-15T09:15:00.000Z to 2024-02-15T10:15:00.000Z. No other changes.
test/test.js Refined existing tests for various .ics files, including updating the expected end time for test_date_time_duration.ics.
test/test_date_time_duration.ics Changed DURATION property in VEVENT from PT15M to PT1H15M, extending the event duration.

Possibly related PRs

  • update to detect duplicate DTSTART/DTEND in same ics event,  #348: The changes in this PR also involve modifications to the END function in ical.js, specifically enhancing error handling and control flow related to event duration, which is closely related to the enhancements made in the main PR regarding duration calculations.

Poem

In the land of code where rabbits play,
Durations grew longer, brightening the day.
With loops and logic, we hop with glee,
Events now last, as long as can be!
So let’s celebrate, with a joyful cheer,
For clearer code brings us all near! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7dd8e11 and b66b57b.

📒 Files selected for processing (4)
  • ical.js (1 hunks)
  • test/test-async.js (1 hunks)
  • test/test.js (1 hunks)
  • test/test_date_time_duration.ics (1 hunks)
🔇 Additional comments (3)
test/test_date_time_duration.ics (1)

16-16: LGTM! Duration format is RFC 5545 compliant.

The updated duration PT1H15M correctly represents a period of 1 hour and 15 minutes, following the iCalendar specification. This test case will help verify the fix for handling multiple time units in duration calculations.

Let's verify other duration formats in the test suite:

✅ Verification successful

Duration format is valid and well-tested across the test suite

The test suite includes a good variety of duration formats that verify different scenarios:

  • Simple durations: PT1H
  • Complex durations with multiple units: PT1H15M
  • Negative durations: -PT1W1D2H3M4S
  • Different time units: hours (H), minutes (M), seconds (S), weeks (W), days (D)

The updated duration PT1H15M in test_date_time_duration.ics complements the existing test cases and helps ensure proper handling of multi-unit durations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for other duration formats in test files to ensure comprehensive testing
# Expect: Various duration formats including multiple time units

# Search for DURATION properties in all .ics files
rg "DURATION:" -A 1 "*.ics"

Length of output: 73


Script:

#!/bin/bash
# Let's try searching with fd first to locate .ics files
fd -e ics

# Then search for DURATION in those files
fd -e ics --exec rg "DURATION:" -A 1 {}

Length of output: 1218

test/test-async.js (1)

854-854: LGTM! The test assertion has been correctly updated.

The change properly reflects the expected end time for an event with a duration of 1 hour and 15 minutes, fixing the handling of multiple time units in duration calculations.

Let's verify that the corresponding .ics file has been updated with the correct duration:

✅ Verification successful

✓ Test assertion matches the ICS file duration

The test assertion expecting end time 2024-02-15T10:15:00.000Z correctly aligns with:

  • Start time: 20240215T090000Z (9:00 AM UTC)
  • Duration: PT1H15M (1 hour and 15 minutes)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the duration in test_date_time_duration.ics matches the test assertion

# Test: Search for DURATION property in the test file
rg "DURATION:|DTSTART:" test/test_date_time_duration.ics

Length of output: 100

test/test.js (1)

1044-1044: LGTM! The test case correctly verifies the duration calculation.

The assertion validates that an event starting at 09:00 UTC with a duration of 1 hour and 15 minutes (PT1H15M) correctly ends at 10:15 UTC.

Let's verify that the test case matches the ICS file:

✅ Verification successful

Test case correctly matches the ICS file specification

The verification confirms that:

  • The ICS file has an event starting at 09:00 UTC (DTSTART:20240215T090000Z)
  • The duration is exactly 1 hour and 15 minutes (DURATION:PT1H15M)
  • This validates that the test assertion checking for an end time of 10:15 UTC is correct, as it properly accounts for the duration
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the duration in the test_date_time_duration.ics file
# Expected: Should find PT1H15M duration

# Test: Search for DURATION property
rg "DURATION:PT1H15M" test/test_date_time_duration.ics

Length of output: 71


Script:

#!/bin/bash
# Let's verify the complete event details in the ICS file
# to ensure start time and other properties match the test case

cat test/test_date_time_duration.ics

Length of output: 448

ical.js Outdated
Comment on lines 473 to 485
const duration = curr.duration.match(/-?\d{1,10}[YMWDHS]/g);

// Use the duration to create the end value, from the start
let newend = moment.utc(curr.start);
let newEnd = moment.utc(curr.start);
// Is the 1st character a negative sign?
const indicator = curr.duration.startsWith('-') ? -1 : 1;
newend = newend.add(Number.parseInt(r, 10) * indicator, durationUnits[r.toString().slice(-1)]);

for (const r of duration) {
newEnd = newEnd.add(Number.parseInt(r, 10) * indicator, durationUnits[r.toString().slice(-1)]);
}

// End is a Date type, not moment
curr.end = newend.toDate();
curr.end = newEnd.toDate();
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Remove unused duration units and add validation.

The duration calculation has been improved to handle multiple time units correctly. However, there are a few suggestions for improvement:

  1. The durationUnits object includes 'Y' (years) and 'M' (months) in the comment, but they're not used. This could be misleading.
  2. There's no validation for invalid duration units.

Consider applying these improvements:

 const durationUnits =
 {
-  // Y: 'years',
-  // M: 'months',
   W: 'weeks',
   D: 'days',
   H: 'hours',
   M: 'minutes',
   S: 'seconds'
 };
 const duration = curr.duration.match(/-?\d{1,10}[YMWDHS]/g);
+// Validate duration units
+for (const r of duration) {
+  const unit = r.slice(-1);
+  if (!durationUnits[unit]) {
+    throw new Error(`Invalid duration unit: ${unit}`);
+  }
+}

 let newEnd = moment.utc(curr.start);

Consider caching the moment object to improve performance when processing multiple duration components:

-let newEnd = moment.utc(curr.start);
+const startMoment = moment.utc(curr.start);
+let newEnd = startMoment;

Committable suggestion was skipped due to low confidence.

@jens-maus
Copy link
Owner

@coderabbitai full review

Copy link

coderabbitai bot commented Oct 28, 2024

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (1)
ical.js (1)

486-486: Consider adding a comment explaining the date conversion.

The conversion from moment to Date type is important but not immediately obvious.

Add a comment to improve code readability:

-curr.end = newEnd.toDate();
+// Convert from moment to Date type as required by the API
+curr.end = newEnd.toDate();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7dd8e11 and 2b90200.

📒 Files selected for processing (4)
  • ical.js (1 hunks)
  • test/test-async.js (1 hunks)
  • test/test.js (1 hunks)
  • test/test_date_time_duration.ics (1 hunks)
🔇 Additional comments (6)
test/test_date_time_duration.ics (1)

16-16: LGTM! The duration format is valid and demonstrates the multiple time units use case.

The updated duration PT1H15M follows the ISO 8601 duration format and correctly represents a period of 1 hour and 15 minutes, which is suitable for testing the handling of multiple time units.

Let's verify the duration format against the iCalendar spec:

✅ Verification successful

LGTM! The duration format is valid and correctly represents the test case.

The duration PT1H15M in the iCalendar file follows the ISO 8601/RFC 5545 format and properly demonstrates the multiple time units use case (1 hour and 15 minutes) for testing the duration calculation fix.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the duration format follows RFC 5545 section 3.3.6
# Expected format: P[n]DT[n]H[n]M[n]S where [n] is a positive integer

# Test: Search for any duration that doesn't match the RFC 5545 format
rg -U 'DURATION:(?!P(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?$)' test/test_date_time_duration.ics

# No output expected, indicating the format is valid

Length of output: 350


Script:

#!/bin/bash
# Let's try a simpler approach to verify the duration format
# First, let's see the full content of the test file
cat test/test_date_time_duration.ics

# Then search for all DURATION lines to verify the format
rg "DURATION:" test/test_date_time_duration.ics

Length of output: 513

ical.js (2)

461-472: LGTM! Duration units are correctly defined.

The duration units are properly defined according to RFC5545 3.3.6, correctly excluding year and month units.


475-477: 🛠️ Refactor suggestion

Consider caching the moment object.

Creating a new moment object and reassigning it in each iteration could impact performance. The startMoment is already created but not fully utilized.

Consider this optimization:

-const startMoment = moment.utc(curr.start);
-let newEnd = startMoment;
+const newEnd = moment.utc(curr.start);

Likely invalid or redundant comment.

test/test-async.js (1)

854-854: LGTM! The updated end time correctly reflects the duration.

The change from 09:15 to 10:15 aligns with the fix for handling multiple time units in duration (PT1H15M = 1 hour and 15 minutes).

Let's verify the corresponding ICS file content:

✅ Verification successful

✅ Verified: The ICS file duration matches the expected end time

The ICS file contains DURATION:PT1H15M which correctly corresponds to the updated test assertion expecting an end time of 10:15 (start time 09:00 + duration of 1 hour and 15 minutes).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the test_date_time_duration.ics file contains the correct DURATION property
# Expected: Should find PT1H15M as the duration value

rg "DURATION:PT1H15M" test/test_date_time_duration.ics

Length of output: 71

test/test.js (2)

1044-1044: LGTM! The updated assertion correctly verifies the duration calculation.

The modified assertion verifies that an event with a duration of 1 hour and 15 minutes (PT1H15M) correctly ends at 10:15:00 UTC when starting at 09:00:00 UTC. This change aligns with the PR's objective of fixing duration calculations with multiple time units.


1043-1044: Verify test coverage for other duration combinations.

While this test case covers a duration with hours and minutes (PT1H15M), it would be beneficial to add more test cases covering other combinations of time units (e.g., days+hours, minutes+seconds) to ensure comprehensive coverage of the duration calculation fix.

Consider adding test cases for these scenarios:

  1. Multiple days + hours (e.g., P2DT5H)
  2. Hours + minutes + seconds (e.g., PT1H30M45S)
  3. Edge cases like single units (PT1H) vs multiple units (PT1H0M)

ical.js Outdated
Comment on lines 481 to 484
for (const r of duration) {
newEnd = newEnd.add(Number.parseInt(r, 10) * indicator, durationUnits[r.toString().slice(-1)]);
}

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add validation for duration units.

The code assumes all duration units in the input are valid. Adding validation would make the code more robust.

Consider adding validation:

 for (const r of duration) {
+  const unit = r.slice(-1);
+  if (!durationUnits[unit]) {
+    throw new Error(`Invalid duration unit: ${unit}`);
+  }
   newEnd = newEnd.add(Number.parseInt(r, 10) * indicator, durationUnits[r.toString().slice(-1)]);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const r of duration) {
newEnd = newEnd.add(Number.parseInt(r, 10) * indicator, durationUnits[r.toString().slice(-1)]);
}
for (const r of duration) {
const unit = r.slice(-1);
if (!durationUnits[unit]) {
throw new Error(`Invalid duration unit: ${unit}`);
}
newEnd = newEnd.add(Number.parseInt(r, 10) * indicator, durationUnits[r.toString().slice(-1)]);
}

@jens-maus jens-maus merged commit d60b2df into jens-maus:master Oct 28, 2024
16 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.

3 participants