• kinttach@lemm.ee
    link
    fedilink
    English
    arrow-up
    20
    ·
    1 year ago

    The legacy Date object has many problems and this is one of them. Another infamous one is that it uses zero-based month numbers: January is the zeroth month and December the 11th month.

    This will be fixed Any Day Now™️ when Temporal is released. This is a carefully designed library that supersedes Date and is currently waiting on some standards to be finalized.

      • ricecake@sh.itjust.works
        link
        fedilink
        arrow-up
        20
        arrow-down
        3
        ·
        1 year ago

        It’s because there’s no right answer, and this way gets you the intuitive answer most often.

        A month isn’t a proper unit of time. Adding a month to a date can’t be done without specifying which month you’re adding.

        You could argue that one month from January 31 is February 28, 29 (depending on the year), March 2, or 3.

        Should one month from the last day be the last day of the next month? That would mean that the 30th and the 31st of march are both the same duration from April 30th, and a month before April 30th could logically map to either one.

        So they chose the path that, for anything other than the 31st, and the 29th and 30th if it comes near February, works as you expect. "A month after 17 days from the first of January is 17 days after the first of february.”

        The other alternatives involve not allowing the addition and subtraction of irregular time intervals, but then you get frustrated that you can only deal with seconds, since those don’t change in length.

        • ☆ Yσɠƚԋσʂ ☆@lemmy.mlOP
          link
          fedilink
          arrow-up
          4
          arrow-down
          13
          ·
          1 year ago

          Having restrictions is far better than having random pitfalls that you fall into. An API works as you’d expect majority of the time and then has an edge case that’s entirely not obvious is a bad API. The whole problem with Js is that it’s full of rakes that you can step on. You can rationalize every one of these weird behaviors in Js, but that doesn’t make the language any easier to work with in practice. People forget a random rule here or there and then their code breaks in weird ways when the stars align just right. This is simply not how APIs should be designed.

          • ricecake@sh.itjust.works
            link
            fedilink
            arrow-up
            4
            arrow-down
            1
            ·
            1 year ago

            In this case though, it’s consistent, and is just one of the annoying ways the problem could be solved. Datetime math is just fucked up.

            You can just not support that functionality, which gives you people making their own mistakes and forgetting leap years or hard coding all sorts of insanity.

            You can clamp the value to the end of the month, but that gives you the odd case where date + month - month != date in some days, which is also a weird pitfall.

            If I see any code dealing with adding and subtracting months, I’m either checking the manual or I already know it’s behavior from doing so before.
            I’m all about not liking how JS does stuff, but Datetime math is the one area where in willing to forgive most insanity of outcomes.

            • ☆ Yσɠƚԋσʂ ☆@lemmy.mlOP
              link
              fedilink
              arrow-up
              2
              arrow-down
              11
              ·
              1 year ago

              One way to solve the problem is to give an error when you end up with an invalid input such as a data outside the range of valid dates for the month. The other way to solve the problem is to silently return nonsense which is what Js does. It’s just a matter of doing basic input validation.

              • ricecake@sh.itjust.works
                link
                fedilink
                arrow-up
                4
                arrow-down
                2
                ·
                1 year ago

                Except it’s not nonsense. If you ask for 31 days after January 31st, you don’t get February 28th.

                A month is a malformed concept to use in conjunction with arithmetic, except for the part where people do it all the time and just ignore the fact that it often gets weird.

                Do you really think you’d be happier if the answer for "what’s a month from 01/31?” was “InvalidDateException”? That every other month the concept of “a month from today” is just undefined?

                Saying “adding a month means adding the number of days in the starting month” is one choice of many, all of which have terrible downsides.

          • railsdev@programming.dev
            link
            fedilink
            arrow-up
            2
            ·
            edit-2
            1 year ago

            I agree here. The convenience it may offer to developers who try it might be nice but the trade off is random craziness. I support not supporting features that are unintuitive. In this case that means not allowing someone to add “one month” to a date.

            • ricecake@sh.itjust.works
              link
              fedilink
              arrow-up
              1
              ·
              1 year ago

              So, the flip side to that is that sometimes you need to add one month to a date, because that sometimes how human systems are written.
              By not providing a function that does that, you’re just pushing the confusion down to the developer, who is more likely to make terrible errors in the process, get frustrated, or use one of N different competing libraries, each of which chose a different answer.

              Omitting functionality that can behave unintuitively in certain circumstances means leaving out a lot of functionality that people need.

              Like, “decimal numbers” go pathological in certain cases. So do Unicode characters. Don’t even bother thinking about connecting to the network.

              • railsdev@programming.dev
                link
                fedilink
                arrow-up
                2
                arrow-down
                2
                ·
                edit-2
                1 year ago

                In Ruby (with ActiveSupport) I would do something like 4.days.from_now or 30.days.from_now.

                If I really needed “one month from now” on some specific day of the month that not every month has I’d do:

                def 31st_of_next_month
                  next_month = (Time.current.end_of_month + 1.day).beginning_of_month
                  day = next_month + 31.days
                  return day if day.month == next_month
                
                  # last day of month if no 31st
                  next_month.end_of_month.beginning_of_day
                end
                

                Disclaimer: I’m laying in bed typing this on mobile. The code probably sucks but I’m writing for illustrative purposes.

            • ☆ Yσɠƚԋσʂ ☆@lemmy.mlOP
              link
              fedilink
              arrow-up
              3
              arrow-down
              9
              ·
              1 year ago

              Exactly, it’s better to not have these sorts of “conveniences” than to create weird pitfalls. I find a lot of crazy Js behaviors are ultimately a result of Js trying to be accommodating of inputs that should just be straight up rejected.

      • erogenouswarzone@lemmy.ml
        link
        fedilink
        English
        arrow-up
        4
        ·
        1 year ago

        I love js. But the date object has always been a total pain. Moment.js is a good package to deal with it, but yeah, it’s currently deprecated, but it would be nice if it or something like it became part of ECMAScript.

        I have no idea why it hasn’t yet, except that it might be that js needs to work for everyone, not just the us. So time is not standard.

        • towerful@programming.dev
          link
          fedilink
          arrow-up
          3
          ·
          edit-2
          1 year ago

          The date API is like the original rip of the Java date API. Barely changed, and totally backwards compatible nonsense.

          Temporal is the new JavaScript/ECMAScript date API.
          It’s stage 3, and likely stable (just a few kinks being worked out). So you could polyfill it for production.
          https://github.com/tc39/proposal-temporal

          • erogenouswarzone@lemmy.ml
            link
            fedilink
            English
            arrow-up
            2
            ·
            1 year ago

            Speaking of Java RipS. How annoying is it the JS has left Java in the dust as far as looser standards?

            Developing in Java: YOU FORGOT A SEMI-COLON ARE YOU CRAZY?! HOW IS THE COMPILER SUPPOSED TO KNOW WHAT TO DO?!

            Developing in JS: Who gives a fuck about semi-colons?

  • PM_ME_FAT_ENBIES@lib.lgbt
    link
    fedilink
    English
    arrow-up
    10
    arrow-down
    3
    ·
    1 year ago

    Oh, because if the month you chose has less than 31 days, it’ll assume the 31st of September is the 1st of October? That’s reasonable.

    • hh93@lemm.ee
      link
      fedilink
      arrow-up
      3
      ·
      1 year ago

      What would you expect “-1 month” to do for a date like 31st of March? Would the result be the same as for “-1 month” on 29th of March?

      If you go back 2 months so the 31st is existing again - should that mean that the result of using -1 month twice should be different to using -2 months?

      I think it’s just a stupid way to implement something like this as “month” isn’t a defined size so defining it with a fixed value and documenting it properly is a decent solution but noone should use that kind of function in the first place

      • mattreb@feddit.it
        link
        fedilink
        arrow-up
        4
        ·
        edit-2
        1 year ago

        It is a stupid way to implement it, but the called function is named setMonth()! The minus one is performed externally, so if you set February you expect February, validation should adjust the other fields…

      • ☆ Yσɠƚԋσʂ ☆@lemmygrad.ml
        link
        fedilink
        arrow-up
        7
        arrow-down
        7
        ·
        1 year ago

        This is literally how every sane API works in languages built by adults. For example, here’s what happens in Java:

        java.time.LocalDate.of(2023, 3, 31)
        > #object[java.time.LocalDate 0x2bc77260 "2023-03-31"]
        java.time.LocalDate.of(2023, 3, 31).minusMonths(1)
        > #object[java.time.LocalDate 0xac0dc15 "2023-02-28"]
        java.time.LocalDate.of(2023, 3, 31).minusMonths(2)
        > #object[java.time.LocalDate 0x44b9305f "2023-01-31"]
        

        I have no idea where people get this notion that a month isn’t a defined size. Do people just not understand the concept of a month?

    • ftatateeta@lemmy.ml
      link
      fedilink
      arrow-up
      1
      ·
      1 year ago

      I would expect the month to increment by one and the day to be clamped to the valid days for the month.