kotlinx-datetime icon indicating copy to clipboard operation
kotlinx-datetime copied to clipboard

Substitute for YearMonth?

Open boswelja opened this issue 3 years ago • 16 comments

java.time has a YearMonth class for referring to a particular month in the year, what's the kotlinx-datetime equivalent? LocalDate also stores a day of the month which isn't ideal

boswelja avatar Dec 21 '21 06:12 boswelja

data class YearMonth(val year: Int, val month: Int) should do the trick.

elizarov avatar Dec 21 '21 07:12 elizarov

data class YearMonth(val year: Int, val month: Month)

for additional type safety.

dkhalanskyjb avatar Dec 21 '21 07:12 dkhalanskyjb

Well yes, but I think it would be nice for the library to provide it out of the box. Wouldn't you agree?

boswelja avatar Dec 21 '21 09:12 boswelja

Do you need this to support any operations that would meaningfully interact with the rest of the library? What functionality would you want from such a class?

dkhalanskyjb avatar Dec 21 '21 09:12 dkhalanskyjb

Things like isLeapYear and isValidDay are handy, but proper support for plus and minus operations would be great.

boswelja avatar Dec 21 '21 09:12 boswelja

  • isValidDay is fairly straightforward: just attempt to construct a LocalDate. Failure means either that the year is very far away, or that the day is invalid. We wouldn't introduce a new data structure just for that unless we expected that it is common for people to know the year and the month and want to check several days-of-month for whether they are valid. Can you think of a popular use case for this?
  • Could you clarify what use you have for isLeapYear? In any case, it doesn't look like YearMonth is a good place for isLeapYear (the month is not relevant at all).
  • What do you plan to use plus and minus for? Of everything listed, a compelling use case for them would be the strongest argument for introducing a YearMonth. I'm interested in high-level details about the problem area, like "I have a calendar app with an exciting new feature: ZZZ. For that, I need to be able to have a YearMonth object and add years and months to it".

dkhalanskyjb avatar Dec 22 '21 10:12 dkhalanskyjb

I agree isValidDate is pretty simple to implement myself, but if I'm importing a date/time library I don't expect to need my own implementation (plus there's probably a nicer way to do it instead of catching LocalDate construction).

isLeapYear probably doesn't have many practical uses, I can see why it makes sense to not include it in a YearMonth and it's possibly too niche to implement.

Funnily enough my use case is a calendar with a month view that the user can swipe through. The current implementation takes a start and end YearMonth and creates it's data by iterating from start to end via plusMonths(1). Having a YearMonth with at least plus is a must for my current approach.

boswelja avatar Dec 23 '21 07:12 boswelja

See also my early draft PR #173 which could be the starting point for arbitrary precision date handling and type safety via sealed interfaces. Medical data comes with date fields containing Year or YearMonth or other arbitrary precision levels (within one single field) and we need to parse, display, sort, compare, etc. such values.

It would be great to have that use-case supported in this lib instead of having everyone reinvent the wheel.

wkornewald avatar Dec 29 '21 19:12 wkornewald

Any updates on this? I'm happy to get something together in a PR, just need to know if it's something the maintainers want to go ahead with

boswelja avatar Feb 19 '22 00:02 boswelja

Another use case for me would be:

  • default serialization format YYYY-MM for kotlinx.serialization implemented like for other temporal classes
  • ability for other kotlin libraries (database, serialization, http frameworks, html <input type="month"> MDN etc.) to standardize on one implementation and cooperate

morki avatar Mar 21 '23 09:03 morki

@morki, this does not explain why this would be useful. Sure, if YearMonth is useful, serialization for it is also useful, and it would be good for the other things to standardize, but why is it useful?

dkhalanskyjb avatar Mar 21 '23 11:03 dkhalanskyjb

For me only as a standardized wrapper with "well known" serialization. For example for parsing <input type="month"> posted in HTTP server etc. From functional point o view, I only use methods like YearMonth.startOfMonth(): LocalDate and YearMonth.endOfMonth(): LocalDate for range filtering in database.

The other useful common type is YearWeek (also <input type="week">). But I understand your position. I just tried to write what I was feeling. Thank you for this awesome library :)

morki avatar Mar 21 '23 11:03 morki

We don't yet have a position to understand, or this issue would be closed one way or another. You're using <input type="month">, but what does it represent, why is <input type="month"> used? The example shown in the Mozilla documentation is "What month were you born in?", which is a question I personally have never seen in the wild, and as a selector used to display the month in a calendar.

Also, ISO 8601 describes serialization for this: 2023-03, basically the initial part of the ISO 8601 date.

dkhalanskyjb avatar Mar 21 '23 11:03 dkhalanskyjb

Calendars, finance apps (your monthly bank statement), fitness apps (you ran how far this month?), sales reports... the concept of a specific month in a specific year is ubiquitous.

GrahamBorland avatar Mar 21 '23 11:03 GrahamBorland

Relevant for me. My use case: thermal energy billing system. Our billing period is a month of the year, based on this we take the number of days in a month and multiply by 24 and get the “service provision time” and then carry out calculations...

SteinerOk avatar Mar 15 '24 02:03 SteinerOk