git.iko.soy/typeable/http-api-data
on master help sign in
Merge pull request #109 from fizruk/time-compat-1.9.5
640178bOleg Grenrus
.ghcideleted−1
@@ -1 +0,0 @@
1−:set -itest -isrc -optP-include -optP .stack-work/dist/x86_64-osx/Cabal-1.24.0.0/build/autogen/cabal_macros.h -optP-I -optPinclude
.github/workflows/haskell-ci.yml+5−5
@@ -110,7 +110,7 @@ jobs:
110 - name: cache (tools)
110 - name: cache (tools)
111 uses: actions/cache@v2
111 uses: actions/cache@v2
112 with:
112 with:
113− key: ${{ runner.os }}-${{ matrix.ghc }}-tools-0f645703
113+ key: ${{ runner.os }}-${{ matrix.ghc }}-tools-b869866c
114 path: ~/.haskell-ci-tools
114 path: ~/.haskell-ci-tools
115 - name: install cabal-plan
115 - name: install cabal-plan
116 run: |
116 run: |
@@ -123,8 +123,8 @@ jobs:
123 cabal-plan --version
123 cabal-plan --version
124 - name: install doctest
124 - name: install doctest
125 run: |
125 run: |
126− if [ $((HCNUMVER >= 80000 && HCNUMVER < 81000)) -ne 0 ] ; then $CABAL --store-dir=$HOME/.haskell-ci-tools/store v2-install $ARG_COMPILER --ignore-project -j2 doctest --constraint='doctest ^>=0.17' ; fi
126+ if [ $((HCNUMVER >= 80000)) -ne 0 ] ; then $CABAL --store-dir=$HOME/.haskell-ci-tools/store v2-install $ARG_COMPILER --ignore-project -j2 doctest --constraint='doctest ^>=0.17' ; fi
127− if [ $((HCNUMVER >= 80000 && HCNUMVER < 81000)) -ne 0 ] ; then doctest --version ; fi
127+ if [ $((HCNUMVER >= 80000)) -ne 0 ] ; then doctest --version ; fi
128 - name: checkout
128 - name: checkout
129 uses: actions/checkout@v2
129 uses: actions/checkout@v2
130 with:
130 with:
@@ -178,8 +178,8 @@ jobs:
178 - name: doctest
178 - name: doctest
179 run: |
179 run: |
180 perl -i -e 'while (<ARGV>) { print unless /package-id\s+(base-compat)-\d+(\.\d+)*/; }' .ghc.environment.*
180 perl -i -e 'while (<ARGV>) { print unless /package-id\s+(base-compat)-\d+(\.\d+)*/; }' .ghc.environment.*
181− if [ $((HCNUMVER >= 80000 && HCNUMVER < 81000)) -ne 0 ] ; then cd ${PKGDIR_http_api_data} || false ; fi
181+ if [ $((HCNUMVER >= 80000)) -ne 0 ] ; then cd ${PKGDIR_http_api_data} || false ; fi
182− if [ $((HCNUMVER >= 80000 && HCNUMVER < 81000)) -ne 0 ] ; then doctest src/ ; fi
182+ if [ $((HCNUMVER >= 80000)) -ne 0 ] ; then doctest src/ ; fi
183 - name: cabal check
183 - name: cabal check
184 run: |
184 run: |
185 cd ${PKGDIR_http_api_data} || false
185 cd ${PKGDIR_http_api_data} || false
CHANGELOG.md+6
@@ -1,3 +1,9 @@
1+0.4.3
2+-----
3+
4+* Add `Quarter`, `QuarterOfYear` and `Month` instances
5+* Support `bytestring-0.11`
6+
10.4.2
70.4.2
2-----
8-----
3
9
cabal.haskell-ci+1−1
@@ -1,5 +1,5 @@
1branches: master
1branches: master
2−doctest: <8.10
2+doctest: True
3doctest-filter-packages: base-compat
3doctest-filter-packages: base-compat
4
4
5constraint-set text-show
5constraint-set text-show
http-api-data.cabal+9−9
@@ -1,6 +1,6 @@
1cabal-version: >= 1.10
1cabal-version: >= 1.10
2name: http-api-data
2name: http-api-data
3−version: 0.4.2
3+version: 0.4.3
4
4
5synopsis: Converting to/from HTTP API data like URL pieces, headers and query parameters.
5synopsis: Converting to/from HTTP API data like URL pieces, headers and query parameters.
6category: Web
6category: Web
@@ -56,15 +56,15 @@ library
56 -- other-dependencies
56 -- other-dependencies
57 build-depends:
57 build-depends:
58 attoparsec >= 0.13.2.2 && < 0.14
58 attoparsec >= 0.13.2.2 && < 0.14
59− , attoparsec-iso8601 >= 1.0.1.0 && < 1.1
59+ , attoparsec-iso8601 >= 1.0.2.0 && < 1.1
60 , base-compat >= 0.10.5 && < 0.12
60 , base-compat >= 0.10.5 && < 0.12
61 , cookie >= 0.4.3 && < 0.5
61 , cookie >= 0.4.3 && < 0.5
62 , hashable >= 1.2.7.0 && < 1.4
62 , hashable >= 1.2.7.0 && < 1.4
63 , http-types >= 0.12.3 && < 0.13
63 , http-types >= 0.12.3 && < 0.13
64 , tagged >= 0.8.5 && < 0.9
64 , tagged >= 0.8.5 && < 0.9
65− , time-compat >= 1.9.2 && < 1.10
65+ , time-compat >= 1.9.5 && < 1.10
66− , unordered-containers >= 0.2.10.0 && < 0.3
66+ , unordered-containers >= 0.2.10.0 && < 0.3
67− , uuid-types >= 1.0.3 && <1.1
67+ , uuid-types >= 1.0.3 && < 1.1
68
68
69 if !impl(ghc >= 7.10)
69 if !impl(ghc >= 7.10)
70 build-depends:
70 build-depends:
@@ -112,10 +112,10 @@ test-suite spec
112 if !impl(ghc >= 7.10)
112 if !impl(ghc >= 7.10)
113 build-depends: nats
113 build-depends: nats
114
114
115− build-depends: HUnit >= 1.6.0.0 && <1.7
115+ build-depends: HUnit >= 1.6.0.0 && <1.7
116− , hspec >= 2.7.1 && <2.8
116+ , hspec >= 2.7.1 && <2.8
117− , QuickCheck >= 2.13.1 && <2.15
117+ , QuickCheck >= 2.13.1 && <2.15
118− , quickcheck-instances >= 0.3.21 && <0.4
118+ , quickcheck-instances >= 0.3.25.2 && <0.4
119
119
120source-repository head
120source-repository head
121 type: git
121 type: git
src/Web/Internal/FormUrlEncoded.hs+8
@@ -52,6 +52,8 @@ import Data.Text.Encoding.Error (lenientDecode)
52import qualified Data.Text.Lazy as Lazy
52import qualified Data.Text.Lazy as Lazy
53import Data.Time.Compat (Day, LocalTime, NominalDiffTime,
53import Data.Time.Compat (Day, LocalTime, NominalDiffTime,
54 UTCTime, ZonedTime)
54 UTCTime, ZonedTime)
55+import Data.Time.Calendar.Month.Compat (Month)
56+import Data.Time.Calendar.Quarter.Compat (Quarter, QuarterOfYear (..))
55import Data.Void (Void)
57import Data.Void (Void)
56import Data.Word (Word16, Word32, Word64, Word8)
58import Data.Word (Word16, Word32, Word64, Word8)
57import GHC.Exts (Constraint, IsList (..))
59import GHC.Exts (Constraint, IsList (..))
@@ -113,6 +115,9 @@ instance ToFormKey LocalTime where toFormKey = toQueryParam
113instance ToFormKey ZonedTime where toFormKey = toQueryParam
115instance ToFormKey ZonedTime where toFormKey = toQueryParam
114instance ToFormKey UTCTime where toFormKey = toQueryParam
116instance ToFormKey UTCTime where toFormKey = toQueryParam
115instance ToFormKey NominalDiffTime where toFormKey = toQueryParam
117instance ToFormKey NominalDiffTime where toFormKey = toQueryParam
118+instance ToFormKey Quarter where toFormKey = toQueryParam
119+instance ToFormKey QuarterOfYear where toFormKey = toQueryParam
120+instance ToFormKey Month where toFormKey = toQueryParam
116
121
117instance ToFormKey String where toFormKey = toQueryParam
122instance ToFormKey String where toFormKey = toQueryParam
118instance ToFormKey Text where toFormKey = toQueryParam
123instance ToFormKey Text where toFormKey = toQueryParam
@@ -172,6 +177,9 @@ instance FromFormKey LocalTime where parseFormKey = parseQueryParam
172instance FromFormKey ZonedTime where parseFormKey = parseQueryParam
177instance FromFormKey ZonedTime where parseFormKey = parseQueryParam
173instance FromFormKey UTCTime where parseFormKey = parseQueryParam
178instance FromFormKey UTCTime where parseFormKey = parseQueryParam
174instance FromFormKey NominalDiffTime where parseFormKey = parseQueryParam
179instance FromFormKey NominalDiffTime where parseFormKey = parseQueryParam
180+instance FromFormKey Quarter where parseFormKey = parseQueryParam
181+instance FromFormKey QuarterOfYear where parseFormKey = parseQueryParam
182+instance FromFormKey Month where parseFormKey = parseQueryParam
175
183
176instance FromFormKey String where parseFormKey = parseQueryParam
184instance FromFormKey String where parseFormKey = parseQueryParam
177instance FromFormKey Text where parseFormKey = parseQueryParam
185instance FromFormKey Text where parseFormKey = parseQueryParam
src/Web/Internal/HttpApiData.hs+66
@@ -55,6 +55,9 @@ import Data.Time.Compat (Day, FormatTime, LocalTime,
55 secondsToNominalDiffTime)
55 secondsToNominalDiffTime)
56import Data.Time.Format.Compat (defaultTimeLocale,
56import Data.Time.Format.Compat (defaultTimeLocale,
57 iso8601DateFormat)
57 iso8601DateFormat)
58+import Data.Time.Calendar.Month.Compat (Month)
59+import Data.Time.Calendar.Quarter.Compat (Quarter, QuarterOfYear (..),
60+ toYearQuarter)
58import Data.Typeable (Typeable)
61import Data.Typeable (Typeable)
59import qualified Data.UUID.Types as UUID
62import qualified Data.UUID.Types as UUID
60import Data.Version (Version, parseVersion,
63import Data.Version (Version, parseVersion,
@@ -516,6 +519,42 @@ instance ToHttpApiData DayOfWeek where
516
519
517 toEncodedUrlPiece = unsafeToEncodedUrlPiece
520 toEncodedUrlPiece = unsafeToEncodedUrlPiece
518
521
522+-- |
523+-- >>> toUrlPiece Q4
524+-- "q4"
525+instance ToHttpApiData QuarterOfYear where
526+ toUrlPiece Q1 = "q1"
527+ toUrlPiece Q2 = "q2"
528+ toUrlPiece Q3 = "q3"
529+ toUrlPiece Q4 = "q4"
530+
531+-- |
532+-- >>> import Data.Time.Calendar.Quarter.Compat (Quarter (..))
533+-- >>> MkQuarter 8040
534+-- 2010-Q1
535+--
536+-- >>> toUrlPiece $ MkQuarter 8040
537+-- "2010-q1"
538+--
539+instance ToHttpApiData Quarter where
540+ toUrlPiece q = case toYearQuarter q of
541+ (y, qoy) -> T.pack (show y ++ "-" ++ f qoy)
542+ where
543+ f Q1 = "q1"
544+ f Q2 = "q2"
545+ f Q3 = "q3"
546+ f Q4 = "q4"
547+
548+-- |
549+-- >>> import Data.Time.Calendar.Month.Compat (Month (..))
550+-- >>> MkMonth 24482
551+-- 2040-03
552+--
553+-- >>> toUrlPiece $ MkMonth 24482
554+-- "2040-03"
555+--
556+instance ToHttpApiData Month where
557+ toUrlPiece = T.pack . formatTime defaultTimeLocale "%Y-%m"
519
558
520instance ToHttpApiData NominalDiffTime where
559instance ToHttpApiData NominalDiffTime where
521 toUrlPiece = toUrlPiece . nominalDiffTimeToSeconds
560 toUrlPiece = toUrlPiece . nominalDiffTimeToSeconds
@@ -704,6 +743,9 @@ instance FromHttpApiData ZonedTime where parseUrlPiece = runAtto Atto.zonedTime
704-- Right 2015-10-03 00:14:24 UTC
743-- Right 2015-10-03 00:14:24 UTC
705instance FromHttpApiData UTCTime where parseUrlPiece = runAtto Atto.utcTime
744instance FromHttpApiData UTCTime where parseUrlPiece = runAtto Atto.utcTime
706
745
746+-- |
747+-- >>> parseUrlPiece "Monday" :: Either Text DayOfWeek
748+-- Right Monday
707instance FromHttpApiData DayOfWeek where
749instance FromHttpApiData DayOfWeek where
708 parseUrlPiece t = case Map.lookup (T.toLower t) m of
750 parseUrlPiece t = case Map.lookup (T.toLower t) m of
709 Just dow -> Right dow
751 Just dow -> Right dow
@@ -715,6 +757,30 @@ instance FromHttpApiData DayOfWeek where
715
757
716instance FromHttpApiData NominalDiffTime where parseUrlPiece = fmap secondsToNominalDiffTime . parseUrlPiece
758instance FromHttpApiData NominalDiffTime where parseUrlPiece = fmap secondsToNominalDiffTime . parseUrlPiece
717
759
760+-- |
761+-- >>> parseUrlPiece "2021-01" :: Either Text Month
762+-- Right 2021-01
763+instance FromHttpApiData Month where parseUrlPiece = runAtto Atto.month
764+
765+-- |
766+-- >>> parseUrlPiece "2021-q1" :: Either Text Quarter
767+-- Right 2021-Q1
768+instance FromHttpApiData Quarter where parseUrlPiece = runAtto Atto.quarter
769+
770+-- |
771+-- >>> parseUrlPiece "q2" :: Either Text QuarterOfYear
772+-- Right Q2
773+--
774+-- >>> parseUrlPiece "Q3" :: Either Text QuarterOfYear
775+-- Right Q3
776+instance FromHttpApiData QuarterOfYear where
777+ parseUrlPiece t = case T.toLower t of
778+ "q1" -> return Q1
779+ "q2" -> return Q2
780+ "q3" -> return Q3
781+ "q4" -> return Q4
782+ _ -> Left "Invalid quarter of year"
783+
718instance FromHttpApiData All where parseUrlPiece = coerce (parseUrlPiece :: Text -> Either Text Bool)
784instance FromHttpApiData All where parseUrlPiece = coerce (parseUrlPiece :: Text -> Either Text Bool)
719instance FromHttpApiData Any where parseUrlPiece = coerce (parseUrlPiece :: Text -> Either Text Bool)
785instance FromHttpApiData Any where parseUrlPiece = coerce (parseUrlPiece :: Text -> Either Text Bool)
720
786
test/Web/Internal/HttpApiDataSpec.hs+6
@@ -14,6 +14,8 @@ import qualified Data.Text as T
14import qualified Data.Text.Encoding as TE
14import qualified Data.Text.Encoding as TE
15import qualified Data.Text.Lazy as L
15import qualified Data.Text.Lazy as L
16import Data.Time.Compat
16import Data.Time.Compat
17+import Data.Time.Calendar.Month.Compat (Month)
18+import Data.Time.Calendar.Quarter.Compat (Quarter, QuarterOfYear (..))
17import qualified Data.UUID.Types as UUID
19import qualified Data.UUID.Types as UUID
18import Data.Version
20import Data.Version
19import Data.Word
21import Data.Word
@@ -87,6 +89,10 @@ spec = do
87 checkUrlPiece (Proxy :: Proxy UTCTime) "UTCTime"
89 checkUrlPiece (Proxy :: Proxy UTCTime) "UTCTime"
88 checkUrlPiece (Proxy :: Proxy NominalDiffTime) "NominalDiffTime"
90 checkUrlPiece (Proxy :: Proxy NominalDiffTime) "NominalDiffTime"
89 checkUrlPiece (Proxy :: Proxy DayOfWeek) "DayOfWeek"
91 checkUrlPiece (Proxy :: Proxy DayOfWeek) "DayOfWeek"
92+ checkUrlPiece (Proxy :: Proxy Quarter) "Quarter"
93+ checkUrlPiece (Proxy :: Proxy QuarterOfYear) "QuarterOfYear"
94+ checkUrlPiece (Proxy :: Proxy Month) "Month"
95+ checkUrlPiece (Proxy :: Proxy DayOfWeek) "DayOfWeek"
90 checkUrlPiece (Proxy :: Proxy Version) "Version"
96 checkUrlPiece (Proxy :: Proxy Version) "Version"
91 checkUrlPiece (Proxy :: Proxy UUID.UUID) "UUID"
97 checkUrlPiece (Proxy :: Proxy UUID.UUID) "UUID"
92 checkUrlPiece' setCookieGen "Cookie"
98 checkUrlPiece' setCookieGen "Cookie"