diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,10 @@
 # Change Log
 
+## [1.12.1] - 2021-10-24
+- add DayPeriod class for periods of days
+- add QuarterDay pattern and DayOfQuarter type synonym
+- add CommonEra and BeforeCommonEra patterns
+
 ## [1.12] - 2021-06-12
 - support GHC 8.8, 8.10, 9.0 only
 - add patterns for each month of year
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Haskell time package 1.12.
+# Generated by GNU Autoconf 2.69 for Haskell time package 1.12.1.
 #
 # Report bugs to <ashley@semantic.org>.
 #
@@ -580,8 +580,8 @@
 # Identity of this package.
 PACKAGE_NAME='Haskell time package'
 PACKAGE_TARNAME='time'
-PACKAGE_VERSION='1.12'
-PACKAGE_STRING='Haskell time package 1.12'
+PACKAGE_VERSION='1.12.1'
+PACKAGE_STRING='Haskell time package 1.12.1'
 PACKAGE_BUGREPORT='ashley@semantic.org'
 PACKAGE_URL=''
 
@@ -1238,7 +1238,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures Haskell time package 1.12 to adapt to many kinds of systems.
+\`configure' configures Haskell time package 1.12.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1300,7 +1300,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Haskell time package 1.12:";;
+     short | recursive ) echo "Configuration of Haskell time package 1.12.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1386,7 +1386,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Haskell time package configure 1.12
+Haskell time package configure 1.12.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1858,7 +1858,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by Haskell time package $as_me 1.12, which was
+It was created by Haskell time package $as_me 1.12.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4193,7 +4193,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by Haskell time package $as_me 1.12, which was
+This file was extended by Haskell time package $as_me 1.12.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -4246,7 +4246,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-Haskell time package config.status 1.12
+Haskell time package config.status 1.12.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([Haskell time package], [1.12], [ashley@semantic.org], [time])
+AC_INIT([Haskell time package],[1.12.1],[ashley@semantic.org],[time])
 
 # Safety check: Ensure that we are in the correct source directory.
 AC_CONFIG_SRCDIR([lib/include/HsTime.h])
diff --git a/lib/Data/Time/Calendar/Days.hs b/lib/Data/Time/Calendar/Days.hs
--- a/lib/Data/Time/Calendar/Days.hs
+++ b/lib/Data/Time/Calendar/Days.hs
@@ -5,6 +5,14 @@
     Day (..),
     addDays,
     diffDays,
+
+    -- * DayPeriod
+    DayPeriod (..),
+    periodAllDays,
+    periodLength,
+    periodFromDay,
+    periodToDay,
+    periodToDayValid,
 ) where
 
 import Control.DeepSeq
@@ -42,3 +50,58 @@
 
 diffDays :: Day -> Day -> Integer
 diffDays (ModifiedJulianDay a) (ModifiedJulianDay b) = a - b
+
+-- | The class of types which can be represented as a period of days.
+--
+-- @since 1.12.1
+class Ord p => DayPeriod p where
+    -- | Returns the first 'Day' in a period of days.
+    periodFirstDay :: p -> Day
+
+    -- | Returns the last 'Day' in a period of days.
+    periodLastDay :: p -> Day
+
+    -- | Get the period this day is in.
+    dayPeriod :: Day -> p
+
+-- | A list of all the days in this period.
+--
+-- @since 1.12.1
+periodAllDays :: DayPeriod p => p -> [Day]
+periodAllDays p = [periodFirstDay p .. periodLastDay p]
+
+-- | The number of days in this period.
+--
+-- @since 1.12.1
+periodLength :: DayPeriod p => p -> Int
+periodLength p = succ $ fromInteger $ diffDays (periodLastDay p) (periodFirstDay p)
+
+-- | Get the period this day is in, with the 1-based day number within the period.
+--
+-- @periodFromDay (periodFirstDay p) = (p,1)@
+--
+-- @since 1.12.1
+periodFromDay :: DayPeriod p => Day -> (p, Int)
+periodFromDay d =
+    let p = dayPeriod d
+        dt = succ $ fromInteger $ diffDays d $ periodFirstDay p
+     in (p, dt)
+
+-- | Inverse of 'periodFromDay'.
+--
+-- @since 1.12.1
+periodToDay :: DayPeriod p => p -> Int -> Day
+periodToDay p i = addDays (toInteger $ pred i) $ periodFirstDay p
+
+-- | Validating inverse of 'periodFromDay'.
+--
+-- @since 1.12.1
+periodToDayValid :: DayPeriod p => p -> Int -> Maybe Day
+periodToDayValid p i =
+    let d = periodToDay p i
+     in if fst (periodFromDay d) == p then Just d else Nothing
+
+instance DayPeriod Day where
+    periodFirstDay = id
+    periodLastDay = id
+    dayPeriod = id
diff --git a/lib/Data/Time/Calendar/Gregorian.hs b/lib/Data/Time/Calendar/Gregorian.hs
--- a/lib/Data/Time/Calendar/Gregorian.hs
+++ b/lib/Data/Time/Calendar/Gregorian.hs
@@ -1,10 +1,13 @@
 {-# LANGUAGE Safe #-}
+{-# LANGUAGE TypeSynonymInstances #-}
 
 {-# OPTIONS -fno-warn-orphans #-}
 
 module Data.Time.Calendar.Gregorian (
     -- * Year, month and day
     Year,
+    pattern CommonEra,
+    pattern BeforeCommonEra,
     MonthOfYear,
     pattern January,
     pattern February,
@@ -46,6 +49,7 @@
 import Data.Time.Calendar.MonthDay
 import Data.Time.Calendar.OrdinalDate
 import Data.Time.Calendar.Private
+import Data.Time.Calendar.Types
 
 -- | Convert to proleptic Gregorian calendar.
 toGregorian :: Day -> (Year, MonthOfYear, DayOfMonth)
@@ -173,3 +177,9 @@
 -- orphan instance
 instance Show Day where
     show = showGregorian
+
+-- orphan instance
+instance DayPeriod Year where
+    periodFirstDay y = YearMonthDay y January 1
+    periodLastDay y = YearMonthDay y December 31
+    dayPeriod (YearMonthDay y _ _) = y
diff --git a/lib/Data/Time/Calendar/Month.hs b/lib/Data/Time/Calendar/Month.hs
--- a/lib/Data/Time/Calendar/Month.hs
+++ b/lib/Data/Time/Calendar/Month.hs
@@ -57,6 +57,11 @@
         m <- readPrec
         return $ YearMonth y m
 
+instance DayPeriod Month where
+    periodFirstDay (YearMonth y m) = YearMonthDay y m 1
+    periodLastDay (YearMonth y m) = YearMonthDay y m 31 -- clips to correct day
+    dayPeriod (YearMonthDay y my _) = YearMonth y my
+
 addMonths :: Integer -> Month -> Month
 addMonths n (MkMonth a) = MkMonth $ a + n
 
@@ -78,18 +83,15 @@
 
 {-# COMPLETE YearMonth #-}
 
-toMonthDay :: Day -> (Month, DayOfMonth)
-toMonthDay (YearMonthDay y my dm) = (YearMonth y my, dm)
-
 -- | Bidirectional abstract constructor.
 -- Invalid days of month will be clipped to the correct range.
 pattern MonthDay :: Month -> DayOfMonth -> Day
 pattern MonthDay m dm <-
-    (toMonthDay -> (m, dm))
+    (periodFromDay -> (m, dm))
     where
-        MonthDay (YearMonth y my) dm = YearMonthDay y my dm
+        MonthDay = periodToDay
 
 fromMonthDayValid :: Month -> DayOfMonth -> Maybe Day
-fromMonthDayValid (YearMonth y my) dm = fromGregorianValid y my dm
+fromMonthDayValid = periodToDayValid
 
 {-# COMPLETE MonthDay #-}
diff --git a/lib/Data/Time/Calendar/Quarter.hs b/lib/Data/Time/Calendar/Quarter.hs
--- a/lib/Data/Time/Calendar/Quarter.hs
+++ b/lib/Data/Time/Calendar/Quarter.hs
@@ -10,6 +10,8 @@
     monthOfYearQuarter,
     monthQuarter,
     dayQuarter,
+    DayOfQuarter,
+    pattern QuarterDay,
 ) where
 
 import Control.DeepSeq
@@ -85,6 +87,21 @@
         m <- readPrec
         return $ YearQuarter y m
 
+instance DayPeriod Quarter where
+    periodFirstDay (YearQuarter y q) =
+        case q of
+            Q1 -> periodFirstDay $ YearMonth y January
+            Q2 -> periodFirstDay $ YearMonth y April
+            Q3 -> periodFirstDay $ YearMonth y July
+            Q4 -> periodFirstDay $ YearMonth y October
+    periodLastDay (YearQuarter y q) =
+        case q of
+            Q1 -> periodLastDay $ YearMonth y March
+            Q2 -> periodLastDay $ YearMonth y June
+            Q3 -> periodLastDay $ YearMonth y September
+            Q4 -> periodLastDay $ YearMonth y December
+    dayPeriod (MonthDay m _) = monthQuarter m
+
 addQuarters :: Integer -> Quarter -> Quarter
 addQuarters n (MkQuarter a) = MkQuarter $ a + n
 
@@ -100,14 +117,29 @@
 
 {-# COMPLETE YearQuarter #-}
 
+-- | The 'QuarterOfYear' this 'MonthOfYear' is in.
 monthOfYearQuarter :: MonthOfYear -> QuarterOfYear
 monthOfYearQuarter my | my <= 3 = Q1
 monthOfYearQuarter my | my <= 6 = Q2
 monthOfYearQuarter my | my <= 9 = Q3
 monthOfYearQuarter _ = Q4
 
+-- | The 'Quarter' this 'Month' is in.
 monthQuarter :: Month -> Quarter
 monthQuarter (YearMonth y my) = YearQuarter y $ monthOfYearQuarter my
 
+-- | The 'Quarter' this 'Day' is in.
 dayQuarter :: Day -> Quarter
-dayQuarter (MonthDay m _) = monthQuarter m
+dayQuarter = dayPeriod
+
+-- | Bidirectional abstract constructor.
+-- Invalid days of quarter will be clipped to the correct range.
+--
+-- @since 1.12.1
+pattern QuarterDay :: Quarter -> DayOfQuarter -> Day
+pattern QuarterDay q dq <-
+    (periodFromDay -> (q, dq))
+    where
+        QuarterDay = periodToDay
+
+{-# COMPLETE QuarterDay #-}
diff --git a/lib/Data/Time/Calendar/Types.hs b/lib/Data/Time/Calendar/Types.hs
--- a/lib/Data/Time/Calendar/Types.hs
+++ b/lib/Data/Time/Calendar/Types.hs
@@ -2,9 +2,27 @@
 
 module Data.Time.Calendar.Types where
 
--- | Year of Common Era.
+-- | Year of Common Era (when positive).
 type Year = Integer
 
+-- | Also known as Anno Domini.
+pattern CommonEra :: Integer -> Year
+pattern CommonEra n <-
+    ((\y -> if y > 0 then Just y else Nothing) -> Just n)
+    where
+        CommonEra n = n
+
+-- | Also known as Before Christ.
+-- Note that Year 1 = 1 CE, and the previous Year 0 = 1 BCE.
+-- 'CommonEra' and 'BeforeCommonEra' form a @COMPLETE@ set.
+pattern BeforeCommonEra :: Integer -> Year
+pattern BeforeCommonEra n <-
+    ((\y -> if y <= 0 then Just (1 - y) else Nothing) -> Just n)
+    where
+        BeforeCommonEra n = 1 - n
+
+{-# COMPLETE CommonEra, BeforeCommonEra #-}
+
 -- | Month of year, in range 1 (January) to 12 (December).
 type MonthOfYear = Int
 
@@ -50,9 +68,12 @@
 -- | Day of month, in range 1 to 31.
 type DayOfMonth = Int
 
+-- | Day of quarter, in range 1 to 92.
+type DayOfQuarter = Int
+
 -- | Day of year, in range 1 (January 1st) to 366.
 -- December 31st is 365 in a common year, 366 in a leap year.
 type DayOfYear = Int
 
--- | Week of year, by various reckonings, generally in range 0-53 depending on reckoning
+-- | Week of year, by various reckonings, generally in range 0-53 depending on reckoning.
 type WeekOfYear = Int
diff --git a/lib/Data/Time/Format/ISO8601.hs b/lib/Data/Time/Format/ISO8601.hs
--- a/lib/Data/Time/Format/ISO8601.hs
+++ b/lib/Data/Time/Format/ISO8601.hs
@@ -153,7 +153,7 @@
 mapWeekDate =
     mapMFormat (\(y, (w, d)) -> fromWeekDateValid y w d) (\day -> (\(y, w, d) -> Just (y, (w, d))) $ toWeekDate day)
 
--- | Like `makeTimeOfDayValid`, but accepts @24 0 0@ per ISO 8601:2004(E) sec. 4.2.3
+-- | Like 'makeTimeOfDayValid', but accepts @24 0 0@ per ISO 8601:2004(E) sec. 4.2.3
 --
 -- @since 1.12
 isoMakeTimeOfDayValid :: Int -> Int -> Pico -> Maybe TimeOfDay
diff --git a/test/main/Main.hs b/test/main/Main.hs
--- a/test/main/Main.hs
+++ b/test/main/Main.hs
@@ -5,6 +5,7 @@
 import Test.Calendar.Calendars
 import Test.Calendar.ClipDates
 import Test.Calendar.ConvertBack
+import Test.Calendar.DayPeriod
 import Test.Calendar.Duration
 import Test.Calendar.Easter
 import Test.Calendar.LongWeekYears
@@ -12,6 +13,7 @@
 import Test.Calendar.MonthOfYear
 import Test.Calendar.Valid
 import Test.Calendar.Week
+import Test.Calendar.Year
 import Test.Clock.Conversion
 import Test.Clock.Resolution
 import Test.Clock.TAI
@@ -37,11 +39,13 @@
             , clipDates
             , convertBack
             , longWeekYears
+            , testDayPeriod
             , testMonthDay
             , testMonthOfYear
             , testEaster
             , testValid
             , testWeek
+            , testYear
             , testDuration
             ]
         , testGroup "Clock" [testClockConversion, testResolutions, testTAI]
diff --git a/test/main/Test/Arbitrary.hs b/test/main/Test/Arbitrary.hs
--- a/test/main/Test/Arbitrary.hs
+++ b/test/main/Test/Arbitrary.hs
@@ -34,8 +34,11 @@
 
 deriving instance Random Day
 
+supportedDayRange :: (Day, Day)
+supportedDayRange = (fromGregorian (-9899) 1 1, fromGregorian 9999 12 31)
+
 instance Arbitrary Day where
-    arbitrary = choose (fromGregorian (-9900) 1 1, fromGregorian 9999 12 31)
+    arbitrary = choose supportedDayRange
     shrink day =
         let (y, m, d) = toGregorian day
             dayShrink =
diff --git a/test/main/Test/Calendar/DayPeriod.hs b/test/main/Test/Calendar/DayPeriod.hs
new file mode 100644
--- /dev/null
+++ b/test/main/Test/Calendar/DayPeriod.hs
@@ -0,0 +1,158 @@
+module Test.Calendar.DayPeriod (
+    testDayPeriod,
+) where
+
+import Data.Time.Calendar
+import Data.Time.Calendar.Month
+import Data.Time.Calendar.Quarter
+import Test.Tasty
+import Test.Tasty.HUnit
+import Test.Tasty.QuickCheck
+
+newtype WDay = MkWDay Day
+    deriving (Eq, Show)
+
+instance Arbitrary WDay where
+    arbitrary = do
+        (MkWYear y) <- arbitrary
+        (MkWMonthOfYear m) <- arbitrary
+        (MkWDayOfMonth d) <- arbitrary
+        pure $ MkWDay $ YearMonthDay y m d
+
+newtype WYear = MkWYear Year
+    deriving (Eq, Show)
+
+instance Arbitrary WYear where
+    arbitrary = fmap MkWYear $ choose (-1000, 3000)
+
+newtype WMonthOfYear = MkWMonthOfYear MonthOfYear
+    deriving (Eq, Show)
+
+instance Arbitrary WMonthOfYear where
+    arbitrary = fmap MkWMonthOfYear $ choose (-5, 17)
+
+newtype WMonth = MkWMonth Month
+    deriving (Eq, Show)
+
+instance Arbitrary WMonth where
+    arbitrary = do
+        (MkWYear y) <- arbitrary
+        (MkWMonthOfYear m) <- arbitrary
+        pure $ MkWMonth $ YearMonth y m
+
+newtype WDayOfMonth = MkWDayOfMonth DayOfMonth
+    deriving (Eq, Show)
+
+instance Arbitrary WDayOfMonth where
+    arbitrary = fmap MkWDayOfMonth $ choose (-5, 35)
+
+newtype WQuarterOfYear = MkWQuarterOfYear QuarterOfYear
+    deriving (Eq, Show)
+
+instance Arbitrary WQuarterOfYear where
+    arbitrary = fmap MkWQuarterOfYear $ elements [Q1 .. Q4]
+
+newtype WQuarter = MkWQuarter Quarter
+    deriving (Eq, Show)
+
+instance Arbitrary WQuarter where
+    arbitrary = do
+        (MkWYear y) <- arbitrary
+        (MkWQuarterOfYear q) <- arbitrary
+        pure $ MkWQuarter $ YearQuarter y q
+
+testDayPeriod :: TestTree
+testDayPeriod =
+    testGroup
+        "DayPeriod"
+        [ testGroup "Day" testDay
+        , testGroup "Month" testMonth
+        , testGroup "Quarter" testQuarter
+        , testGroup "Year" testYear
+        ]
+
+testDay :: [TestTree]
+testDay =
+    [ testProperty "periodFirstDay" $ \(MkWDay d) ->
+        periodFirstDay d == d
+    , testProperty "periodLastDay" $ \(MkWDay d) ->
+        periodLastDay d == d
+    , testProperty "dayPeriod" $ \(MkWDay d) ->
+        dayPeriod d == d
+    , testProperty "periodAllDays" $ \(MkWDay d) ->
+        periodAllDays d == [d]
+    , testProperty "periodLength" $ \(MkWDay d) ->
+        periodLength d == 1
+    ]
+
+testMonth :: [TestTree]
+testMonth =
+    [ testProperty "periodFirstDay" $ \(MkWMonth my@(YearMonth y m)) ->
+        periodFirstDay my == YearMonthDay y m 1
+    , testGroup
+        "periodLastDay"
+        [ testCase "leap year" $
+            periodLastDay (YearMonth 2024 February) @?= YearMonthDay 2024 February 29
+        , testCase "regular year" $
+            periodLastDay (YearMonth 2023 February) @?= YearMonthDay 2023 February 28
+        ]
+    , testProperty "dayPeriod" $ \(MkWMonth my@(YearMonth y m), MkWDayOfMonth d) ->
+        dayPeriod (YearMonthDay y m d) == my
+    , testProperty "periodAllDays" $ \(MkWMonth my@(YearMonth y1 m1)) ->
+        all (== (y1, m1)) $ map (\(YearMonthDay y2 m2 _) -> (y2, m2)) $ periodAllDays my
+    , testGroup
+        "periodLength"
+        [ testProperty "property tests" $ \(MkWMonth my) ->
+            periodLength my >= 28
+        , testCase "leap year" $
+            periodLength (YearMonth 2024 February) @?= 29
+        , testCase "regular year" $
+            periodLength (YearMonth 2023 February) @?= 28
+        ]
+    ]
+
+testQuarter :: [TestTree]
+testQuarter =
+    [ testGroup
+        "periodFirstDay"
+        [ testProperty "Q1" $ \(MkWYear y) ->
+            periodFirstDay (YearQuarter y Q1) == YearMonthDay y January 1
+        , testProperty "Q2" $ \(MkWYear y) ->
+            periodFirstDay (YearQuarter y Q2) == YearMonthDay y April 1
+        , testProperty "Q3" $ \(MkWYear y) ->
+            periodFirstDay (YearQuarter y Q3) == YearMonthDay y July 1
+        , testProperty "Q4" $ \(MkWYear y) ->
+            periodFirstDay (YearQuarter y Q4) == YearMonthDay y October 1
+        ]
+    , testGroup
+        "periodLastDay"
+        [ testProperty "Q1" $ \(MkWYear y) ->
+            periodLastDay (YearQuarter y Q1) == YearMonthDay y March 31
+        , testProperty "Q2" $ \(MkWYear y) ->
+            periodLastDay (YearQuarter y Q2) == YearMonthDay y June 30
+        , testProperty "Q3" $ \(MkWYear y) ->
+            periodLastDay (YearQuarter y Q3) == YearMonthDay y September 30
+        , testProperty "Q4" $ \(MkWYear y) ->
+            periodLastDay (YearQuarter y Q4) == YearMonthDay y December 31
+        ]
+    , testProperty "dayPeriod" $ \(MkWMonth my@(YearMonth y m), MkWDayOfMonth d) ->
+        dayPeriod (YearMonthDay y m d) == monthQuarter my
+    , testProperty "periodAllDays" $ \(MkWQuarter q) ->
+        all (== q) $ map dayQuarter $ periodAllDays q
+    , testProperty "periodLength" $ \(MkWQuarter q) ->
+        periodLength q >= 90
+    ]
+
+testYear :: [TestTree]
+testYear =
+    [ testProperty "periodFirstDay" $ \(MkWYear y) ->
+        periodFirstDay y == YearMonthDay y January 1
+    , testProperty "periodLastDay" $ \(MkWYear y) ->
+        periodLastDay y == YearMonthDay y December 31
+    , testProperty "dayPeriod" $ \(MkWYear y, MkWMonthOfYear m, MkWDayOfMonth d) ->
+        dayPeriod (YearMonthDay y m d) == y
+    , testProperty "periodAllDays" $ \(MkWYear y1) ->
+        all (== y1) $ map (\(YearMonthDay y2 _ _) -> y2) $ periodAllDays y1
+    , testProperty "periodLength" $ \(MkWYear y) ->
+        periodLength y >= 365
+    ]
diff --git a/test/main/Test/Calendar/Year.hs b/test/main/Test/Calendar/Year.hs
new file mode 100644
--- /dev/null
+++ b/test/main/Test/Calendar/Year.hs
@@ -0,0 +1,29 @@
+module Test.Calendar.Year (
+    testYear,
+) where
+
+import Data.Time.Calendar
+import Data.Time.Calendar.OrdinalDate
+import Test.Arbitrary ()
+import Test.Tasty
+import Test.Tasty.HUnit
+import Test.TestUtil
+
+cbRoundTrip :: TestTree
+cbRoundTrip = nameTest "CE-BCE" $ \(YearDay y _) -> case y of
+    CommonEra n -> case id y of
+        BeforeCommonEra _ -> False
+        _ -> n >= 1 && y == CommonEra n
+    _ -> case id y of
+        BeforeCommonEra n -> n >= 1 && y == BeforeCommonEra n
+        _ -> False
+
+testYear :: TestTree
+testYear =
+    nameTest
+        "Year"
+        [ cbRoundTrip
+        , nameTest "succ 1" $ assertEqual "" (BeforeCommonEra 1) $ succ $ BeforeCommonEra 2
+        , nameTest "succ 2" $ assertEqual "" (CommonEra 1) $ succ $ BeforeCommonEra 1
+        , nameTest "succ 3" $ assertEqual "" (CommonEra 2) $ succ $ CommonEra 1
+        ]
diff --git a/test/main/Test/Format/ISO8601.hs b/test/main/Test/Format/ISO8601.hs
--- a/test/main/Test/Format/ISO8601.hs
+++ b/test/main/Test/Format/ISO8601.hs
@@ -17,8 +17,9 @@
 
 deriving instance Eq ZonedTime
 
-readShowProperty :: (Eq a, Show a) => Format a -> a -> Property
-readShowProperty fmt val =
+readShowProperty :: (Eq a, Show a) => (a -> Bool) -> Format a -> a -> Property
+readShowProperty skip _ val | skip val = property Discard
+readShowProperty _ fmt val =
     case formatShowM fmt val of
         Nothing -> property Discard
         Just str ->
@@ -37,16 +38,22 @@
     specialTestValues = []
 
 instance SpecialTestValues TimeOfDay where
-    specialTestValues = [TimeOfDay 0 0 0, TimeOfDay 24 0 0]
+    specialTestValues = [TimeOfDay 0 0 0, TimeOfDay 0 0 60, TimeOfDay 1 0 60, TimeOfDay 24 0 0]
 
+readShowTestCheck :: (Eq a, Show a, Arbitrary a, SpecialTestValues a) => (a -> Bool) -> Format a -> [TestTree]
+readShowTestCheck skip fmt = [nameTest "random" $ readShowProperty skip fmt, nameTest "special" $ fmap (\a -> nameTest (show a) $ readShowProperty skip fmt a) $ filter (not . skip) specialTestValues]
+
 readShowTest :: (Eq a, Show a, Arbitrary a, SpecialTestValues a) => Format a -> [TestTree]
-readShowTest fmt = [nameTest "random" $ readShowProperty fmt, nameTest "special" $ fmap (\a -> nameTest (show a) $ readShowProperty fmt a) specialTestValues]
+readShowTest = readShowTestCheck $ \_ -> False
 
 readBoth :: NameTest t => (FormatExtension -> t) -> [TestTree]
 readBoth fmts = [nameTest "extended" $ fmts ExtendedFormat, nameTest "basic" $ fmts BasicFormat]
 
+readShowTestsCheck :: (Eq a, Show a, Arbitrary a, SpecialTestValues a) => (a -> Bool) -> (FormatExtension -> Format a) -> [TestTree]
+readShowTestsCheck skip fmts = readBoth $ \fe -> readShowTestCheck skip $ fmts fe
+
 readShowTests :: (Eq a, Show a, Arbitrary a, SpecialTestValues a) => (FormatExtension -> Format a) -> [TestTree]
-readShowTests fmts = readBoth $ \fe -> readShowTest $ fmts fe
+readShowTests = readShowTestsCheck $ \_ -> False
 
 newtype Durational t = MkDurational {unDurational :: t}
     deriving (Eq)
@@ -91,8 +98,8 @@
         , nameTest "expandedWeekDateFormat" $ readShowTests $ expandedWeekDateFormat 6
         , nameTest "expandedYearWeekFormat" $ readShowTests $ expandedYearWeekFormat 6
         , nameTest "timeOfDayFormat" $ readShowTests $ timeOfDayFormat
-        , nameTest "hourMinuteFormat" $ readShowTests $ hourMinuteFormat
-        , nameTest "hourFormat" $ readShowTest $ hourFormat
+        , nameTest "hourMinuteFormat" $ readShowTestsCheck (\(TimeOfDay _ _ s) -> s >= 60) $ hourMinuteFormat
+        , nameTest "hourFormat" $ readShowTestCheck (\(TimeOfDay _ _ s) -> s >= 60) $ hourFormat
         , nameTest "withTimeDesignator" $ readShowTests $ \fe -> withTimeDesignator $ timeOfDayFormat fe
         , nameTest "withUTCDesignator" $ readShowTests $ \fe -> withUTCDesignator $ timeOfDayFormat fe
         , nameTest "timeOffsetFormat" $ readShowTests $ timeOffsetFormat
diff --git a/test/main/Test/Format/ParseTime.hs b/test/main/Test/Format/ParseTime.hs
--- a/test/main/Test/Format/ParseTime.hs
+++ b/test/main/Test/Format/ParseTime.hs
@@ -14,7 +14,7 @@
 import Data.Time.Calendar.OrdinalDate
 import Data.Time.Calendar.Quarter
 import Data.Time.Calendar.WeekDate
-import Test.Arbitrary ()
+import Test.Arbitrary (supportedDayRange)
 import Test.QuickCheck.Property
 import Test.Tasty
 import Test.Tasty.HUnit
@@ -592,6 +592,10 @@
         "format_parse_format"
         [ localOption (QuickCheckTests 50000) $
             nameTest "general" $ allTypes $ \name p -> nameTest name $ prop_format_parse_format p
+        , nameTest "#177" $
+            [ nameTest "start" $ \fc -> prop_format_parse_format Proxy fc (fst supportedDayRange)
+            , nameTest "end" $ \fc -> prop_format_parse_format Proxy fc (snd supportedDayRange)
+            ]
         , nameTest "leapsecond" $ allLeapSecondTypes $ \name t -> nameTest name $ \fc -> prop_format_parse_format Proxy fc t
         ]
 
diff --git a/time.cabal b/time.cabal
--- a/time.cabal
+++ b/time.cabal
@@ -1,6 +1,6 @@
 cabal-version:  3.0
 name:           time
-version:        1.12
+version:        1.12.1
 stability:      stable
 license:        BSD-2-Clause
 license-file:   LICENSE
@@ -14,7 +14,7 @@
 build-type:     Configure
 tested-with:
     GHC == 8.8.4,
-    GHC == 8.10.5,
+    GHC == 8.10.7,
     GHC == 9.0.1
 x-follows-version-policy:
 
@@ -73,13 +73,13 @@
         Data.Time
     other-modules:
         Data.Format,
-        Data.Time.Calendar.Types,
-        Data.Time.Calendar.Private,
+        Data.Time.Calendar.CalendarDiffDays,
         Data.Time.Calendar.Days,
         Data.Time.Calendar.Gregorian,
-        Data.Time.Calendar.CalendarDiffDays,
-        Data.Time.Calendar.Week,
         Data.Time.Calendar.JulianYearDay,
+        Data.Time.Calendar.Private,
+        Data.Time.Calendar.Types,
+        Data.Time.Calendar.Week,
         Data.Time.Clock.Internal.DiffTime,
         Data.Time.Clock.Internal.AbsoluteTime,
         Data.Time.Clock.Internal.NominalDiffTime,
@@ -163,6 +163,7 @@
         Test.Calendar.Duration
         Test.Calendar.Easter
         Test.Calendar.EasterRef
+        Test.Calendar.DayPeriod
         Test.Calendar.LongWeekYears
         Test.Calendar.LongWeekYearsRef
         Test.Calendar.MonthDay
@@ -170,6 +171,7 @@
         Test.Calendar.MonthOfYear
         Test.Calendar.Valid
         Test.Calendar.Week
+        Test.Calendar.Year
         Test.Clock.Conversion
         Test.Clock.Resolution
         Test.Clock.TAI
