• ☆ Yσɠƚԋσʂ ☆@lemmy.mlOP
    link
    fedilink
    arrow-up
    4
    arrow-down
    11
    ·
    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
        8
        ·
        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.

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

              What behavior do you expect? Specifically.

              I’m arguing that every answer is wrong, and will return bizarre results, be aggravating, useless or some combination therein for some conditions.
              Therefore you have to know the API, because every language will fuck you, and JavaScript isn’t special in this specific case.

              Adding the number of days in the month to the date as “add one month” is just as rational as any other choice.

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

                The behavior I would expect would be to throw an error when the date is outside of the range of valid dates for the month. If you try to create a date on February 31st throw an error. Have you seriously never used a good API that’s intuitive and isn’t full of gotchas?

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

                  Have you never done Datetime math before?

                  You didn’t run new Date(2019, 02, 31), you asked it for one month from January 31st.
                  One month after any given day of the month is, by most people’s intuition, a valid thing to ask for.

                  Your solution of making the API throw an exception for every 31st of the year is vastly less intuitive to me than “a month is 31 days in January, and 28 or 29 in February, so adding a month does different things in different months”, because at least for those is can also query how many days are in the month.

                  If I say to add four days, will it throw an exception if it’s the 31st? No month has 35 days, so I should get an exception, right?
                  Or is it just this weird caveat around months? Does it apply to time?

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

                    One month after any given day of the month is, by most people’s intuition, a valid thing to ask for.

                    Nobody actually thinks this way, when you ask somebody what’s the next month they don’t go, oh today is the x day of the month and I’m going to add days to the current date to see what’s the next month. That’s not how vast majority of people think about this intuitively. Clearly you and people who designed Js Date API do though.

                    “a month is 31 days in January, and 28 or 29 in February, so adding a month does different things in different months”

                    That’s how months work. Each month has a different number of days.

                    If I say to add four days, will it throw an exception if it’s the 31st? No month has 35 days, so I should get an exception, right?

                    Yeah, it’s how months work.

                    In fact, this isn’t a hypothetical argument this is how date APIs work in sane languages like Java. For example:

                    java.time.LocalDate.of(2023, 2, 31)
                    > java.time.DateTimeException: Invalid date 'FEBRUARY 31'
                    
                    java.time.LocalDate.of(2023, 2, 3)
                    > #object[java.time.LocalDate 0x2bc77260 "2023-02-03"]
                    

                    The fact that you think what Js API dies is preferable to this is frankly surreal to me.

    • 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
        7
        ·
        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.