Skip to content

add WeekdaySet, a collection of Weekday that is Copy #1676

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

Merged
merged 1 commit into from
Mar 23, 2025

Conversation

Kinrany
Copy link
Contributor

@Kinrany Kinrany commented Mar 15, 2025

Overview

Adds WeekdaySet: a type that represents a set of Weekdays, stored as a bitmask in one byte.

All functionality is in module weekdays behind a new feature experimental_weekdays.

The API aims to mirror that of standard collections and the underlying BitFlags where appropriate.

This PR is currently a draft that aims to demonstrate a basic implementation.

Motivation

It is somewhat common to schedule events to happen every week, on certain days of the week.

Implementing a type like this on top of chrono plus a library like bitflags or enumflags2 (used in this PR as an implementation detail) is easy, I've personally done this from scratch at least three times by now.

However there are a lot of minor API design decisions to make, making it unlikely that two hand-rolled implementations will be compatible with each other and easy to unify. Similarly, an external type is always going to be less ergonomic than a native chrono implementation.

One specific area where standardizing on a single type in chrono will help is serialization: serde (implemented here in chrono) and database types (implemented in database drivers).

On the other hand, I believe that the desired overall shape of the feature is very clear and not controversial. To put it in one sentence: we'd like to have a collection of Weekdays that is Copy and has the size of one byte while providing all the normal features of collections.

Prior art

The most famous example is probably cron's fifth argument. For example, 0 0 * * 1,3,5 means "at 00:00:00 on Monday, Wednesday or Friday".

iCalendar (RFC 5545) specifies field BYDAY that allows values like MO,TU,SA,SU.

icu_calendar, part of https://github.com/unicode-org/icu4x, uses chrono but implements its own type WeekdaySet.

weekdays is a new package that focuses on this very issue.

Future changes

The implementation could become slightly simpler in the future if Weekday was changed to use one bit for each weekday instead of the numbers from 0 to 6. This should make the conversions between Weekday and WeekdaySet slightly simpler and more efficient. This would be a breaking change of course.

Copy link

codecov bot commented Mar 15, 2025

Codecov Report

Attention: Patch coverage is 91.57509% with 23 lines in your changes missing coverage. Please review.

Project coverage is 91.09%. Comparing base (fa957cc) to head (a8ab4ea).
Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
src/weekdays.rs 91.57% 23 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1676      +/-   ##
==========================================
+ Coverage   91.06%   91.09%   +0.02%     
==========================================
  Files          37       38       +1     
  Lines       17454    17742     +288     
==========================================
+ Hits        15895    16162     +267     
- Misses       1559     1580      +21     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@djc
Copy link
Member

djc commented Mar 16, 2025

I'm open to merging something like this, but I don't want to take on a fat extra dependency for it. For chrono, I think hand-coding something like this (struct WeekdaySet(u8)) should be okay.

@Kinrany
Copy link
Contributor Author

Kinrany commented Mar 16, 2025

I'll check back later in case there are any more MSRV-related failures.

I don't expect this to be the final version, but it should be close enough now. I removed enumflags2, and as a nice side effect there is now a number of methods that can all be const.

@Kinrany
Copy link
Contributor Author

Kinrany commented Mar 16, 2025

I'm looking at examples of code I've written before and adding everything that I think would be universally useful and improve ergonomics of this type. But I would be perfectly happy to limit the first PR to the parts that are the least controversial and don't need more design/bikeshedding.

@Kinrany
Copy link
Contributor Author

Kinrany commented Mar 16, 2025

I'm also force-pushing to keep the PR history somewhat clean, but only when I break checks. Let me know if this becomes an inconvenience or is a bad idea in general 😄

@Kinrany Kinrany changed the title Strawman PR: add Weekdays, a collection of Weekday that is Copy add Weekdays, a collection of Weekday that is Copy Mar 16, 2025
@djc
Copy link
Member

djc commented Mar 16, 2025

This should be a single commit, so force pushing is great. Keeping this somewhat small by limiting the number of traits implemented for this PR would be nice.

@Kinrany
Copy link
Contributor Author

Kinrany commented Mar 16, 2025

Cool cool. I'll keep the local PR history for now to keep track of the additions and then squash once we're close to landing.

Though I've already added everything I could think of for now.

Improved ergonomics are a big reason people keep writing these types over just using Vec<Weekday> or HashSet<Weekday>, so long term we'll probably still want a somewhat wide API, everything that has a single obviously correct and convenient implementation.

If compile times are an issue, hiding the type behind a feature would work great I think. I expect that there are many use cases that don't care about weekdays at all, and then there are use cases that need an arbitrary subset of these methods and impls.

I'll write up a list of things that I consider more questionable.

@Kinrany
Copy link
Contributor Author

Kinrany commented Mar 23, 2025

All the removed code is in Kinrany#1 for now.

@Kinrany Kinrany changed the title add Weekdays, a collection of Weekday that is Copy add WeekdaySet, a collection of Weekday that is Copy Mar 23, 2025
@Kinrany
Copy link
Contributor Author

Kinrany commented Mar 23, 2025

All resolved, except that I kept split_at as a private method.

I also added from_array, as we need some way to construct literal values.

I see the code coverage warnings and this definitely needs a few more tests, but I'd like to make sure there are no more design changes needed first.

@djc djc merged commit 4f4e95b into chronotope:main Mar 23, 2025
35 checks passed
@djc
Copy link
Member

djc commented Mar 23, 2025

Thanks, this looks like a good start. Going to make some tweaks in a followup PR.

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