Can't subtract two floats

I’m revisiting rescript after some time, and this is making me feel stupid:

open Belt

module Hours = {
  let diffDateStrings = (start: string, end: option<string>) => {
    if Option.isNone(end) {
      0
    } else {
      let a = Js.Date.fromString(start)
      let b = Js.Date.fromString(Option.getExn(end))
      open Belt.Float
      Js.Date.getTime(b) - Js.Date.getTime(a)
    }
  }
}

The error message is not helpful:

[E] Line 11, column 6:
This has type: float
  Somewhere wanted: int
  
  You can convert float to int with Belt.Float.toInt.
  If this is a literal, try a number without a trailing dot (e.g. 20).

playground

Ok, so here is te solution:

open Belt

module Hours = {
  let diffDateStrings = (start: string, end: option<string>) => {
    if Option.isNone(end) {
      0.0
    } else {
      let a = Js.Date.fromString(start)
      let b = Js.Date.fromString(Option.getExn(end))
      open Belt.Float
      Js.Date.getTime(b) - Js.Date.getTime(a)
    }
  }
}

so stupid…

Did you check the docs? Primitive Types | ReScript Language Manual

Float requires other operators: +. , -. , *. , /. , etc. Like 0.5 +. 0.6 .

1 Like

Yes, I did but couldn’t find the docs by searching minus.
However, I had that information already on my mind, and tried -. first, but the compiler also complaint:

[E] Line 10, column 6:
This has type: float
  Somewhere wanted: int
  
  You can convert float to int with Belt.Float.toInt.
  If this is a literal, try a number without a trailing dot (e.g. 20).

So yeah, the error was that the first branch was returning 0 (int) rather than float

And here is amore idiomatic version

open Belt

@gentype
module Hours = {
  let diffDateStrings = (start: string, end: option<string>) => {
    switch (start, end) {
    | (_, None) => 0.0
    | (_, Some(e)) => {
        let a = Js.Date.fromString(start)
        let b = Js.Date.fromString(e)
        Js.Date.getTime(b) -. Js.Date.getTime(a)
      }
    }
  }
}

``
1 Like

Quick question, why not use date-fns? It would be basically differenceInMilliseconds(parseISO(start), parseISO(stop)). There are already bindings: https://github.com/SllyQ/bs-date-fns

Also, since you’re never checking start in the pattern match, you don’t need it there. I would write this as:

module Hours = {
  let diffDateStrings = (~end=?, start) =>
    end->Belt.Option.mapWithDefault(0., e => {
      open DateFns
      differenceInMillisecondsf(
        parseISO(e),
        parseISO(start))
    })
}

hey, thanks for the answer. You’re right about the switch statement. My code compiles to dependency free JS, does tho one you posted too? I mean not only date-fns, but also belt

About functions fns… yes, I could, but this is just me translating existing pieces of my code to try rescript.
Also, some times I just want to write good old code. Libraries have their drawbacks, like being harder to debug and understand. Also date-fns is one of the largest pieces of my bundle, so if I can get rid of it I will be happy.

True, date-fns is a dependency, but from what I heard it’s really good at tree-shaking, so…YMMV.