I'm trying to convert a timestamp (ex: "1493287973015") from a JSON to a Date type.
So far I created this custom decoder:
stringToDate : Decoder String -> Decoder Date
stringToDate decoder =
customDecoder decoder Date.fromTime
But it doesn't work because it has return a Result, not a Date:
Function `customDecoder` is expecting the 2nd argument to be:
Time.Time -> Result String a
But it is:
Time.Time -> Date.Date
Is there a way to do a conversion?
Assuming your JSON is actually placing the numeric value inside quotes (meaning you are parsing the JSON value "1493287973015"
and not 1493287973015
), your decoder could look like this:
import Json.Decode exposing (..)
import Date
import String
stringToDate : Decoder Date.Date
stringToDate =
string
|> andThen (\val ->
case String.toFloat val of
Err err -> fail err
Ok ms -> succeed <| Date.fromTime ms)
Notice that stringToDate
doesn't get passed any parameters, as opposed to your example in which you were attempting to pass a Decoder String
as a parameter. That's not quite how decoders work.
Instead, this can be done by building upon more primitive decoders, in this case, we start with the decoder string
from Json.Decode
.
The andThen
portion then takes the string value given by the decoder, and tries to parse it to a float. If it is a valid Float
, it is fed into Date.fromTime
, otherwise, it's a failure.
The fail
and succeed
functions wrap up the normal values you're dealing with into Decoder Date.Date
contexts so they can be returned.
Two things, a JSON may actually have the milliseconds as an integer, not a string and things have changed since v 0.19 of Elm.
Given that your JSON looks something like.
{
...
"someTime": 1552483995395,
...
}
Then this would decode to a Time.Posix:
import Json.Decode as Decode
decodeTime : Decode.Decoder Time.Posix
decodeTime =
Decode.int
|> Decode.andThen
(\ms ->
Decode.succeed <| Time.millisToPosix ms
)