@@ -11,19 +11,23 @@ import Protolude (
11
11
($) ,
12
12
(&) ,
13
13
(/=) ,
14
+ (<&>) ,
14
15
(<>) ,
15
16
)
16
17
import Protolude qualified as P
17
18
18
- import Data.Aeson (decode , eitherDecode )
19
+ import Data.Aeson (decode , eitherDecode , eitherDecodeStrictText )
19
20
import Data.Hourglass (
20
21
DateTime ,
21
22
Elapsed (Elapsed ),
22
23
ElapsedP (ElapsedP ),
23
24
Time (timeFromElapsedP ),
24
25
timeGetDateTimeOfDay ,
26
+ timePrint ,
27
+ toFormat ,
25
28
)
26
- import Data.Text as T (unpack )
29
+ import Data.Text (unpack )
30
+ import Data.Text qualified as T
27
31
import Database.SQLite.Simple (query_ )
28
32
import Database.SQLite.Simple qualified as Sql
29
33
import Test.Hspec (
@@ -82,7 +86,7 @@ import TaskToNote (TaskToNote)
82
86
import TaskToNote qualified
83
87
import TaskToTag (TaskToTag )
84
88
import TaskToTag qualified
85
- import Utils (parseUlidText , parseUlidUtcSection , parseUtc )
89
+ import Utils (parseUlidText , parseUlidUtcSection , parseUtc , ulid2utc )
86
90
87
91
88
92
withMemoryDb :: Config -> (Sql. Connection -> IO a ) -> IO a
@@ -341,6 +345,43 @@ testSuite conf now = do
341
345
runFilter conf now memConn [" " ] `shouldThrow` (== ExitFailure 1 )
342
346
343
347
describe " Import & Export" $ do
348
+ it " parses any sensible datetime string" $ do
349
+ -- TODO: Maybe keep microseconds and nanoseconds
350
+ -- , ("YYYY-MM-DDTH:MI:S.msusZ", "2024-03-15T22:20:05.637913Z")
351
+ -- , ("YYYY-MM-DDTH:MI:S.msusnsZ", "2024-03-15T22:20:05.637913438Z")
352
+
353
+ let dateMap :: [(Text , Text )] =
354
+ [ (" YYYY-MM-DD" , " 2024-03-15" )
355
+ , (" YYYY-MM-DD H:MI" , " 2024-03-15 22:20" )
356
+ , (" YYYY-MM-DDTH:MIZ" , " 2024-03-15T22:20Z" )
357
+ , (" YYYY-MM-DD H:MI:S" , " 2024-03-15 22:20:05" )
358
+ , (" YYYY-MM-DDTH:MI:SZ" , " 2024-03-15T22:20:05Z" )
359
+ , (" YYYYMMDDTHMIS" , " 20240315T222005" )
360
+ , (" YYYY-MM-DDTH:MI:S.msZ" , " 2024-03-15T22:20:05.637Z" )
361
+ , (" YYYY-MM-DDTH:MI:S.msZ" , " 2024-03-15T22:20:05.637123Z" )
362
+ , (" YYYY-MM-DDTH:MI:S.msZ" , " 2024-03-15T22:20:05.637123456Z" )
363
+ ]
364
+
365
+ P. forM_ dateMap $ \ (formatTxt, utcTxt) -> do
366
+ case parseUtc utcTxt of
367
+ Nothing -> P. die " Invalid UTC string"
368
+ Just utcStamp ->
369
+ let timeFmt = formatTxt & T. unpack & toFormat
370
+ in (utcStamp & timePrint timeFmt)
371
+ `shouldBe` T. unpack
372
+ ( utcTxt
373
+ & T. replace " 123" " "
374
+ & T. replace " 456" " "
375
+ )
376
+
377
+ let
378
+ utcTxt = " 2024-03-15T22:20:05.386777444Z"
379
+ printFmt = " YYYY-MM-DDTH:MI:S.ms" & T. unpack & toFormat
380
+ -- Truncates microseconds and nanoseconds
381
+ expected = " 2024-03-15T22:20:05.386"
382
+
383
+ (utcTxt & parseUtc <&> timePrint printFmt) `shouldBe` Just expected
384
+
344
385
it " imports a JSON task" $ do
345
386
withMemoryDb conf $ \ memConn -> do
346
387
let jsonTask = " {\" body\" :\" Just a test\" , \" notes\" :[\" A note\" ]}"
@@ -363,8 +404,7 @@ testSuite conf now = do
363
404
taskToNote `shouldSatisfy` (\ task -> task. note == " A note" )
364
405
_ -> P. die " More than one task_to_note row found"
365
406
366
- tasks :: [FullTask ] <-
367
- query_ memConn " SELECT * FROM tasks_view"
407
+ tasks :: [FullTask ] <- query_ memConn " SELECT * FROM tasks_view"
368
408
369
409
case tasks of
370
410
[updatedTask] -> do
@@ -385,6 +425,27 @@ testSuite conf now = do
385
425
}
386
426
_ -> P. die " More than one task found"
387
427
428
+ it " imports a JSON task with an ISO8601 created_at field" $ do
429
+ withMemoryDb conf $ \ memConn -> do
430
+ let
431
+ utc = " 2024-03-15T10:32:51.386777444Z"
432
+ -- ULID only has millisecond precision:
433
+ utcFromUlid = " 2024-03-15 10:32:51.387"
434
+ jsonTask =
435
+ " {\" body\" :\" Just a test\" ,\" created_at\" :\" {{utc}}\" }"
436
+ & T. replace " {{utc}}" utc
437
+
438
+ case eitherDecodeStrictText jsonTask of
439
+ Left error ->
440
+ P. die $ " Error decoding JSON: " <> show error
441
+ Right importTaskRecord -> do
442
+ _ <- insertImportTask memConn importTaskRecord
443
+ tasks :: [FullTask ] <- query_ memConn " SELECT * FROM tasks_view"
444
+ case tasks of
445
+ [updatedTask] ->
446
+ ulid2utc updatedTask. ulid `shouldBe` Just utcFromUlid
447
+ _ -> P. die " More than one task found"
448
+
388
449
389
450
main :: IO ()
390
451
main = do
0 commit comments