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

Formatting time ranges that cross the next-day boundary isn't possible with Luxon #1662

Open
morungos opened this issue Oct 15, 2024 · 0 comments

Comments

@morungos
Copy link

Is your feature request related to a problem? Please describe.

Yes, the issue is that the standard JS algorithm makes it impossible to get a localized time-only string for a range when that range crosses a day boundary -- even when it is implied by the time difference. Consider:

> (new Intl.DateTimeFormat('en-CA', {timeStyle: 'short'}))
    .formatRange(new Date("2024-09-17 19:00"), new Date("2024-09-18 02:00"))
"2024-09-17, 7:00 p.m.–2024-09-18, 2:00 a.m." 

Because the end is not on the same day as the start, the JS localization standard appears to demand the day be inserted into both of them. That is unfortunate, as the desired "7:00 p.m.–2:00 a.m." is fairly intuitive. As far as I read the standard and the documentation, there is no way to prevent the dates being emitted, only to format them a little if they are.

Describe the solution you'd like

Strangely, standard JavaScript can render a time range where the end is before the start. The problem is, there is no way I can find to do this in Luxon, because the interval constructors are stricter, and there's no direct access to the formatter's .formatRange(). So my hack was going to be to simply bring the end point back one day, which works in JS, but isn't compatible with Luxon.

So, one option might be to somehow expose the underlying JS formatter and/or .formatRange(), so that a user can explicitly pass their own start and end, which might be supplied separately. Note that .formatRange() cannot simply be approximated by formatting the start and end and concatenating them. (For one thing, whether or not there are spaces around a range emdash varies a lot by locale -- trust me, that was a surprise to me too).

Alternatively, but oddly, another option might be to permit the end of an interval to be before the start. Although I recognize that is a very unusual request, but I'm boxed in a bit here by JS, and frankly there may be a point where I should just drop back to standard JS Dates, which I can at least coerce into rendering the way I need them to, as this shows.

> (new Intl.DateTimeFormat('en-CA', {timeStyle: 'short'}))
    .formatRange(new Date("2024-09-17 19:00"), new Date("2024-09-17 02:00")) 
"7:00 p.m.–2:00 a.m."

Describe alternatives you've considered

I've tried using .toFormat() with a localized time, but formatting an interval/range as specified like this has a significant advantage -- it does elide the meridiems when they are the same. .toFormat() doesn't, so then you need to parse out the meridiems, which is nasty and defeats the purpose.

The only other option is to drop down to standard JS, which does allow the ranges to be rendered, even though it is something of a hack.

Additional context

Part of me feels this is a JS standards issue, and could have been considered as part of the standard. In effect, like the way meridiems get elided when they are the same, e.g., "7:00PM-8:00PM" becomes "7:00-8:00PM", a similar logic could/should also apply to dates when the date is sequentially the next day, because the non-elided meridiems in "7:00PM-6:00AM" imply the next date anyway. Arguably, the same should even apply in the 24 hour clock, "19:00-03:00" inevitably implies the end of the interval is on the next day. But it isn't, and I have to fight my way through what there is.

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

No branches or pull requests

1 participant