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

docs: adr choosing a date and time handling solution #8

Open
wants to merge 5 commits into
base: v0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions adr/choosing-a-date-time-handling-solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# ADR: Choosing a Date and Time Handling Solution

## Status

Accepted, decided on Temporal API.

## Context

In modern web applications, accurate and efficient handling of dates and times is crucial. Traditional JavaScript `Date`` objects have several limitations and pitfalls, including:
- Lack of support for different calendars
- Difficulties with time zone conversions
- Ambiguous and error-prone APIs for date and time manipulation

These issues often lead to bugs and inefficiencies in handling date and time data, especially in complex applications that require extensive date and time manipulations, such as calendar applications.

## Decision

After evaluating several options, we have decided to adopt the Temporal API for all date and time handling in our application. Temporal is a new standard for working with dates and times in JavaScript, designed to provide a more reliable, readable, and easy-to-use API.

### Evaluation of Alternatives

1. **JavaScript `Date`**
- **Pros**:
- Built-in and requires no additional dependencies.
- Supported natively in all JavaScript environments.
- **Cons**:
- Ambiguous and error-prone API.
- Poor support for time zones and different calendars.
- Mutable objects, leading to potential bugs.
- Date arithmetic is complex and error-prone.

2. **moment.js**
- **Pros**:
- Widely used and battle-tested.
- Rich feature set for date manipulation and formatting.
- **Cons**:
- Large library size, affecting bundle size.
- Mutable objects, leading to potential bugs.
- Moment.js is in maintenance mode, with no new features planned.

3. **date-fns**
- **Pros**:
- Modular approach, allowing selective imports to reduce bundle size.
- Immutable and functional API.
- Good support for date arithmetic and formatting.
- **Cons**:
- Limited support for time zones without additional libraries.
- Requires combining multiple functions for complex operations.

### Reasons for Choosing Temporal

1. **Clarity and Readability**: Temporal's API is designed to be intuitive and readable. For example, creating a date in Temporal is straightforward and unambiguous:
```javascript
const date = Temporal.PlainDate.from('2024-06-01');
```
This is much clearer than the equivalent using `Date`:
```javascript
const date = new Date('2024-06-01');
```

2. **Immutability**: Temporal objects are immutable, meaning that once created, they cannot be changed. This immutability prevents common bugs related to date manipulation and makes the code easier to reason about.

3. **Comprehensive Support for Calendars and Time Zones**: Temporal natively supports different calendars and time zones, making it ideal for applications that need to handle internationalization and localization.

4. **Precise Arithmetic Operations**: Temporal provides precise and easy-to-use methods for date and time arithmetic, avoiding the pitfalls of JavaScript `Date` arithmetic:
```javascript
const nextMonth = date.add({ months: 1 });
```

5. **Better Error Handling**: Temporal's API is designed to throw errors for invalid operations, which helps in catching bugs early in the development process.

6. **Standardization**: Temporal is an upcoming standard for date and time handling in JavaScript, which means it will have long-term support and improvements from the community and browser vendors.

## Consequences

### Positive

- **Reduced Bugs**: By using Temporal, we expect to see a reduction in date and time-related bugs, especially those related to time zone conversions and date arithmetic.
- **Improved Code Quality**: The clarity and immutability of Temporal will lead to more readable and maintainable code.
- **Enhanced Features**: Support for multiple calendars and time zones will allow us to build more robust and feature-rich internationalized applications.

### Negative

- **Learning Curve**: Developers will need to learn the new Temporal API, which might slow down initial development.
- **Polyfill Requirement**: Until Temporal is fully supported in all target environments, we will need to include a polyfill, which may slightly increase the bundle size.

## Conclusion

After evaluating various options for date and time handling in JavaScript, we have decided to adopt the Temporal API. Temporal provides a robust, readable, and reliable API that addresses the shortcomings of the existing `Date` object and offers comprehensive support for internationalization and time zone handling. Despite the initial learning curve and the need for a polyfill, the long-term benefits make Temporal the best choice for our application's needs.

By documenting this decision, we ensure that future developers understand the rationale behind adopting Temporal and can build upon this foundation with confidence.
4 changes: 2 additions & 2 deletions packages/time/src/tests/isValidDate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {isValidDate} from '../utils/isValidDate';
describe('isValidDate', () => {
test('should return true for a valid date', () => {
expect(isValidDate(new Date())).toBe(true);
});
})

test('should return false for an invalid date', () => {
expect(isValidDate(new Date("invalid"))).toBe(false);
Expand All @@ -13,4 +13,4 @@ describe('isValidDate', () => {
test("should return false for null", () => {
expect(isValidDate(null)).toBe(false);
});
});
});