14

I would like to convert a full date/time to ISO 8601 format like JavaScript's new Date().toISOString() does, giving a YYYY-MM-DDTHH:mm:ss.sssZ format.

I cannot find a base library function or package to do this.

Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286
nh2
  • 24,526
  • 11
  • 79
  • 128

2 Answers2

17

I don't see any pre-existing function for doing this, but you can make one easily using Data.Time.Format.formatTime:

import System.Locale (defaultTimeLocale)
import Data.Time.Format (formatTime)

iso8601 :: UTCTime -> String
iso8601 = formatTime defaultTimeLocale "%FT%T%QZ"

(You need to convert the time to a UTCTime before passing it to this function in order for it to actually display the actual UTC time.)

dsign
  • 12,340
  • 6
  • 59
  • 82
jwodder
  • 54,758
  • 12
  • 108
  • 124
  • 2
    Nice answer. It seems to give a few more digits behind the dot than I asked for though - so let's cut them off: `iso8601 t = take 23 (formatTime defaultTimeLocale "%FT%T%Q" t) ++ "Z"` will do though (found in [the aeson source code](http://hackage.haskell.org/package/aeson-0.6.1.0/docs/src/Data-Aeson-Types-Class.html#FromJSON)]. – nh2 Oct 26 '13 at 23:50
  • 2
    Note that my comment before still does not insert trailing zeroes. I have also released a package [iso8601-time](http://hackage.haskell.org/package/iso8601-time) on Hackage right now that deals with it. – nh2 Oct 27 '13 at 00:38
  • 1
    Saved my day having to convert an IsoDate from MongoDB to UTCTime: `parseTimestamp = parseTimeOrError False defaultTimeLocale "%FT%T%QZ"` – Mikkel May 14 '15 at 08:50
  • Thanks! Just saved my bacon too. I might do a pull request to Data.Persist. Nuts it took me hours to yak shave a simple date input. – Chad Brewbaker May 01 '16 at 17:31
  • 5 years later, it turns out this isn't quite correct. See [this issue](https://github.com/nh2/iso8601-time/issues/10) in the package I created; also see this for where `aeson` got it wrong. `%F` formats year 999 as `999` and not `0999` as required by ISO 8601. – nh2 Aug 29 '18 at 23:41
  • In 2022 I got the error `Could not load module 'System.Locale'` but after I added `old-locale-1.0.0.7` to my cabal file it was fixed. – beyarkay Sep 08 '22 at 08:46
3

The time library in version 1.9 added this functionality (docs):

iso8601Show :: ISO8601 t => t -> String

and UTCTime has a ISO8601 instance.

nh2
  • 24,526
  • 11
  • 79
  • 128