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

GH-40 Add simple duration util #40

Closed
wants to merge 3 commits into from
Closed

Conversation

P1otrulla
Copy link
Member

@P1otrulla P1otrulla commented Oct 11, 2024

Summary by CodeRabbit

  • New Features

    • Introduced SimpleDurationUtil class for formatting Duration objects in Java.
    • Added methods for flexible duration formatting, with options to include or exclude milliseconds.
  • Tests

    • Implemented unit tests for SimpleDurationUtil to ensure accurate formatting of durations under various scenarios.

@P1otrulla P1otrulla changed the title Add simple duration util GH-40 Add simple duration util Oct 11, 2024
Copy link

coderabbitai bot commented Oct 11, 2024

Walkthrough

The pull request introduces a new utility class, SimpleDurationUtil, located in the eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time directory. This class is designed to format Duration objects in Java, featuring two static constants: ONE_SECOND and ZERO_SECONDS. It utilizes two instances of TemporalAmountParser<Duration>WITHOUT_MILLIS_FORMAT for durations without milliseconds and STANDARD_FORMAT for those that include milliseconds.

The class provides two overloaded static methods named format. The first method accepts a Duration and a boolean flag removeMillis, which dictates whether to exclude milliseconds in the output. The second method defaults removeMillis to false. Additionally, a new test file, SimpleDurationUtilTest.java, has been created to validate the functionality of the format method through three distinct unit tests that assess various scenarios of duration formatting. No changes were made to the declarations of exported or public entities in the test file.

Poem

🐇 In the land of time, we found a way,
To format durations, bright as day!
With seconds and millis, all in a row,
Our SimpleDurationUtil steals the show!
So hop along, let’s cheer and play,
For time is now clear, hip-hip-hooray! 🎉


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 24fa44a and 482047f.

📒 Files selected for processing (1)
  • eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java

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: 3

🧹 Outside diff range and nitpick comments (3)
eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java (2)

31-41: LGTM with a minor suggestion: format method logic is sound.

The method effectively uses the removeMillis flag to determine the formatting approach, and handles the special case for durations less than one second when removeMillis is true.

Consider extracting the magic string "0s" to use the ZERO_SECONDS constant for consistency:

 if (duration.toMillis() < ONE_SECOND.toMillis()) {
-    return "0s";
+    return ZERO_SECONDS;
 }

1-48: LGTM: Well-implemented duration formatting utility with minor suggestions.

The SimpleDurationUtil class provides a comprehensive and flexible solution for formatting Duration objects. The implementation is clean, well-structured, and effectively fulfills its purpose.

Consider the following suggestions for further improvement:

  1. Add JavaDoc comments to the class and public methods to provide clear documentation of their purpose and usage.
  2. Consider adding private constructor to prevent instantiation, as this is a utility class with only static methods.

Example improvements:

/**
 * Utility class for formatting Duration objects into human-readable strings.
 */
public class SimpleDurationUtil {

    private SimpleDurationUtil() {
        throw new UnsupportedOperationException("Utility class");
    }

    // ... (other code remains the same)

    /**
     * Formats a Duration into a human-readable string.
     *
     * @param duration The Duration to format
     * @param removeMillis If true, milliseconds are excluded from the output
     * @return A formatted string representation of the Duration
     */
    public static String format(Duration duration, boolean removeMillis) {
        // ... (method body remains the same)
    }

    /**
     * Formats a Duration into a human-readable string, including milliseconds.
     *
     * @param duration The Duration to format
     * @return A formatted string representation of the Duration, including milliseconds
     */
    public static String format(Duration duration) {
        // ... (method body remains the same)
    }
}

These changes would enhance the usability and maintainability of the class.

eternalcode-commons-shared/test/com/eternalcode/commons/time/SimpleDurationUtilTest.java (1)

79-88: Enhance default format testing and add assertion messages

The testFormatDefault method can be improved in the following ways:

  1. Add assertion messages to make debugging easier.
  2. Include more test cases to cover a wider range of scenarios.

Consider the following improvements:

  1. Add descriptive assertion messages to each assertion:
-        assertEquals("10m10s", result);
+        assertEquals("10m10s", result, "Duration of 610 seconds should be formatted as '10m10s'");

-        assertEquals("120ms", result);
+        assertEquals("120ms", result, "Duration of 120 milliseconds should be formatted as '120ms'");
  1. Add more test cases to cover different scenarios, such as:
    • A duration with hours, minutes, and seconds
    • A duration with days
    • A duration with weeks or months
    • A duration with years

For example:

duration = Duration.ofHours(25);
result = SimpleDurationUtil.format(duration);
assertEquals("1d1h", result, "Duration of 25 hours should be formatted as '1d1h'");

duration = Duration.ofDays(400);
result = SimpleDurationUtil.format(duration);
assertEquals("1y1mo5d", result, "Duration of 400 days should be formatted as '1y1mo5d'");

These additional test cases will help ensure the default formatting behavior is correct across various duration ranges.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 5963e2e and 24fa44a.

📒 Files selected for processing (2)
  • eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java (1 hunks)
  • eternalcode-commons-shared/test/com/eternalcode/commons/time/SimpleDurationUtilTest.java (1 hunks)
🧰 Additional context used
🔇 Additional comments (5)
eternalcode-commons-shared/src/main/java/com/eternalcode/commons/time/SimpleDurationUtil.java (5)

1-6: LGTM: Class declaration and imports are appropriate.

The package name, class name, and imports are well-chosen and relevant to the utility's purpose of formatting Duration objects.


8-9: LGTM: Constants are well-defined and appropriately named.

The ONE_SECOND and ZERO_SECONDS constants are clearly named and will be useful in the formatting logic.


11-19: LGTM: WITHOUT_MILLIS_FORMAT parser is well-configured.

The parser is comprehensively set up to handle durations from seconds to years, rounding off to the nearest millisecond. This aligns well with its purpose of formatting durations without millisecond precision.


21-29: LGTM: STANDARD_FORMAT parser is well-configured.

The STANDARD_FORMAT parser extends the capabilities of WITHOUT_MILLIS_FORMAT by including milliseconds, providing a comprehensive solution for standard duration formatting with full precision.


43-45: LGTM: Overloaded format method provides good default behavior.

This overloaded method offers a convenient way to format durations with milliseconds by default, maintaining a clean and intuitive API.

Comment on lines +1 to +89
package com.eternalcode.commons.time;

import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.Duration;
import org.junit.jupiter.api.Test;

public class SimpleDurationUtilTest {

@Test
public void testFormatWithoutMillis() {
Duration duration = Duration.ofMillis(500);
String result = SimpleDurationUtil.format(duration, true);
assertEquals("0s", result);

duration = Duration.ofSeconds(30);
result = SimpleDurationUtil.format(duration, true);
assertEquals("30s", result);

duration = Duration.ofMinutes(5);
result = SimpleDurationUtil.format(duration, true);
assertEquals("5m", result);

duration = Duration.ofHours(2);
result = SimpleDurationUtil.format(duration, true);
assertEquals("2h", result);

duration = Duration.ofDays(1);
result = SimpleDurationUtil.format(duration, true);
assertEquals("1d", result);

duration = Duration.ofDays(14);
result = SimpleDurationUtil.format(duration, true);
assertEquals("2w", result);

duration = Duration.ofDays(60);
result = SimpleDurationUtil.format(duration, true);
assertEquals("2mo", result);

duration = Duration.ofDays(365 * 3);
result = SimpleDurationUtil.format(duration, true);
assertEquals("3y", result);
}

@Test
public void testFormatWithMillis() {
Duration duration = Duration.ofMillis(500);
String result = SimpleDurationUtil.format(duration, false);
assertEquals("500ms", result);

duration = Duration.ofSeconds(30);
result = SimpleDurationUtil.format(duration, false);
assertEquals("30s", result);

duration = Duration.ofMinutes(5);
result = SimpleDurationUtil.format(duration, false);
assertEquals("5m", result);

duration = Duration.ofHours(2);
result = SimpleDurationUtil.format(duration, false);
assertEquals("2h", result);

duration = Duration.ofDays(1);
result = SimpleDurationUtil.format(duration, false);
assertEquals("1d", result);

duration = Duration.ofDays(14);
result = SimpleDurationUtil.format(duration, false);
assertEquals("2w", result);

duration = Duration.ofDays(60);
result = SimpleDurationUtil.format(duration, false);
assertEquals("2mo", result);

duration = Duration.ofDays(365 * 3);
result = SimpleDurationUtil.format(duration, false);
assertEquals("3y", result);
}

@Test
public void testFormatDefault() {
Duration duration = Duration.ofSeconds(610);
String result = SimpleDurationUtil.format(duration);
assertEquals("10m10s", result);

duration = Duration.ofMillis(120);
result = SimpleDurationUtil.format(duration);
assertEquals("120ms", result);
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance overall test class structure and coverage

While the test class covers the main functionality of SimpleDurationUtil, there are several areas where it can be improved:

  1. Add a class-level Javadoc comment explaining the purpose of the test class.
  2. Include tests for edge cases and error scenarios.
  3. Improve the organization of test methods.

Consider the following improvements:

  1. Add a class-level Javadoc comment:
/**
 * Test class for SimpleDurationUtil.
 * This class contains unit tests to verify the correct functioning
 * of the SimpleDurationUtil.format method under various scenarios.
 */
public class SimpleDurationUtilTest {
    // ... existing code ...
}
  1. Add tests for edge cases and error scenarios:
@Test
public void testFormatZeroDuration() {
    Duration duration = Duration.ZERO;
    String result = SimpleDurationUtil.format(duration);
    assertEquals("0s", result, "Zero duration should be formatted as '0s'");
}

@Test
public void testFormatNegativeDuration() {
    Duration duration = Duration.ofSeconds(-60);
    String result = SimpleDurationUtil.format(duration);
    assertEquals("-1m", result, "Negative duration should be formatted with a minus sign");
}

@Test
public void testFormatMaxDuration() {
    Duration duration = Duration.ofSeconds(Long.MAX_VALUE);
    String result = SimpleDurationUtil.format(duration);
    // Assert the expected result for maximum duration
}
  1. Improve organization using nested classes or descriptive naming:
class SimpleDurationUtilTest {

    @Nested
    class FormatWithoutMillis {
        @Test
        void shouldFormatSecondsWithoutMillis() {
            // ... test case for seconds ...
        }

        @Test
        void shouldFormatMinutesWithoutMillis() {
            // ... test case for minutes ...
        }

        // ... other test methods ...
    }

    @Nested
    class FormatWithMillis {
        // ... similar structure for with-millis tests ...
    }

    @Nested
    class FormatDefault {
        // ... default format test methods ...
    }

    @Nested
    class EdgeCases {
        // ... edge case test methods ...
    }
}

These improvements will enhance the overall structure, readability, and coverage of the test class.

Comment on lines +9 to +42
@Test
public void testFormatWithoutMillis() {
Duration duration = Duration.ofMillis(500);
String result = SimpleDurationUtil.format(duration, true);
assertEquals("0s", result);

duration = Duration.ofSeconds(30);
result = SimpleDurationUtil.format(duration, true);
assertEquals("30s", result);

duration = Duration.ofMinutes(5);
result = SimpleDurationUtil.format(duration, true);
assertEquals("5m", result);

duration = Duration.ofHours(2);
result = SimpleDurationUtil.format(duration, true);
assertEquals("2h", result);

duration = Duration.ofDays(1);
result = SimpleDurationUtil.format(duration, true);
assertEquals("1d", result);

duration = Duration.ofDays(14);
result = SimpleDurationUtil.format(duration, true);
assertEquals("2w", result);

duration = Duration.ofDays(60);
result = SimpleDurationUtil.format(duration, true);
assertEquals("2mo", result);

duration = Duration.ofDays(365 * 3);
result = SimpleDurationUtil.format(duration, true);
assertEquals("3y", result);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve test method clarity and add assertion messages

The test method testFormatWithoutMillis has a few areas for improvement:

  1. The method name suggests testing without milliseconds, but the includeMillis parameter is set to true. This is counterintuitive and may lead to confusion.
  2. The test cases lack assertion messages, which could make debugging failures more difficult.

Consider the following improvements:

  1. Rename the method to testFormatWithoutMillis to accurately reflect its purpose.
  2. Change the SimpleDurationUtil.format(duration, true) calls to SimpleDurationUtil.format(duration, false) to match the method name.
  3. Add descriptive assertion messages to each assertion. For example:
-        assertEquals("0s", result);
+        assertEquals("0s", result, "Duration of 500ms should be formatted as '0s' without milliseconds");

Apply this pattern to all assertions in the method.

Committable suggestion was skipped due to low confidence.

Comment on lines +44 to +77
@Test
public void testFormatWithMillis() {
Duration duration = Duration.ofMillis(500);
String result = SimpleDurationUtil.format(duration, false);
assertEquals("500ms", result);

duration = Duration.ofSeconds(30);
result = SimpleDurationUtil.format(duration, false);
assertEquals("30s", result);

duration = Duration.ofMinutes(5);
result = SimpleDurationUtil.format(duration, false);
assertEquals("5m", result);

duration = Duration.ofHours(2);
result = SimpleDurationUtil.format(duration, false);
assertEquals("2h", result);

duration = Duration.ofDays(1);
result = SimpleDurationUtil.format(duration, false);
assertEquals("1d", result);

duration = Duration.ofDays(14);
result = SimpleDurationUtil.format(duration, false);
assertEquals("2w", result);

duration = Duration.ofDays(60);
result = SimpleDurationUtil.format(duration, false);
assertEquals("2mo", result);

duration = Duration.ofDays(365 * 3);
result = SimpleDurationUtil.format(duration, false);
assertEquals("3y", result);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve test method clarity and add assertion messages

The test method testFormatWithMillis has similar issues to the previous method:

  1. The method name suggests testing with milliseconds, but the includeMillis parameter is set to false. This is counterintuitive and may lead to confusion.
  2. The test cases lack assertion messages, which could make debugging failures more difficult.

Consider the following improvements:

  1. Rename the method to testFormatWithMillis to accurately reflect its purpose.
  2. Change the SimpleDurationUtil.format(duration, false) calls to SimpleDurationUtil.format(duration, true) to match the method name.
  3. Add descriptive assertion messages to each assertion. For example:
-        assertEquals("500ms", result);
+        assertEquals("500ms", result, "Duration of 500ms should be formatted as '500ms' with milliseconds");

Apply this pattern to all assertions in the method.

Committable suggestion was skipped due to low confidence.

Copy link
Member

@Rollczi Rollczi left a comment

Choose a reason for hiding this comment

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

To jest omijanie błędu który został dodany do commonsów

@Rollczi
Copy link
Member

Rollczi commented Oct 11, 2024

This way you avoid bugs casued by commits to DurationParser by @vLuckyyy

@Rollczi Rollczi closed this Oct 11, 2024
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.

4 participants