diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+# Changelog for korea-holidays
+
+## Unreleased changes
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Mo Kweon
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,27 @@
+# korea-holidays
+
+[![Build Status](https://travis-ci.com/kkweon/korea-holidays.svg?branch=master)](https://travis-ci.com/kkweon/korea-holidays)
+
+*korea-holidays* is a Haskell library to check if a given date is a Korean
+Holiday.
+
+## Usage
+
+```haskell
+import qualified Data.Holiday.Korea as Korea
+
+Korea.getHoliday 2000 1 1 `shouldBe` Just Korea.Holiday
+  { Korea.date = Korea.MD (1, 1)
+  , Korea.name = "SinJeong"
+  }
+```
+
+## Add to your dependency
+
+In your `package.yaml`
+
+```yaml
+library:
+  dependencies:
+  - korea-holidays
+```
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/korea-holidays.cabal b/korea-holidays.cabal
new file mode 100644
--- /dev/null
+++ b/korea-holidays.cabal
@@ -0,0 +1,66 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.31.2.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: a8d419efde392376f47b6becba96f548c6574a9663ce5c0a39e936a018a86b3d
+
+name:           korea-holidays
+version:        0.1.0.0
+synopsis:       Korea Holidays
+description:    Please see the README on GitHub at <https://github.com/kkweon/korea-holidays#readme>
+category:       Time
+homepage:       https://github.com/githubuser/korea-holidays#readme
+bug-reports:    https://github.com/githubuser/korea-holidays/issues
+author:         Kyung Mo Kweon
+maintainer:     kkweon@gmail.com
+copyright:      2019 Kyung Mo Kweon
+license:        MIT
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    ChangeLog.md
+
+source-repository head
+  type: git
+  location: https://github.com/githubuser/korea-holidays
+
+library
+  exposed-modules:
+      Data.Holiday.Korea
+      Data.Holiday.Model
+  other-modules:
+      Util.Config
+      Paths_korea_holidays
+  hs-source-dirs:
+      src
+  build-depends:
+      aeson
+    , base >=4.7 && <5
+    , monad-extras
+    , split
+    , template-haskell
+    , yaml
+  default-language: Haskell2010
+
+test-suite korea-holidays-test
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Data.Holiday.KoreaSpec
+      Paths_korea_holidays
+  hs-source-dirs:
+      test
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      aeson
+    , base >=4.7 && <5
+    , hspec
+    , korea-holidays
+    , monad-extras
+    , split
+    , template-haskell
+    , yaml
+  default-language: Haskell2010
diff --git a/src/Data/Holiday/Korea.hs b/src/Data/Holiday/Korea.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Holiday/Korea.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+{-|
+Module      : Data.Holiday.Korea
+Description : The module contains Korea Holidays
+Copyright   : (c) Kyung Mo Kweon
+License     : BSD
+Maintainer  : kkweon@gmail.com
+Stability   : experimental
+Portability : POSIX
+
+The module contains Korea Holidays
+-}
+module Data.Holiday.Korea where
+
+import Data.Aeson.Types (FromJSON, (.:), parseJSON, withObject)
+import Data.Holiday.Model (Date(..), Holiday(..))
+import Data.Maybe (fromJust, listToMaybe)
+import Util.Config (holidays)
+
+-- | 'getHoliday' returns Nothing if there is no Korean holiday.
+getHoliday ::
+     Integer -- ^ Year
+  -> Int -- ^ Month
+  -> Int -- ^ Day
+  -> Maybe Holiday
+getHoliday year month day = listToMaybe $ filter match holidays
+  where
+    match :: Holiday -> Bool
+    match Holiday {date = YMD (y, m, d)}
+      | y == year && m == month && d == day = True
+    match Holiday {date = MD (m, d)}
+      | m == month && d == day = True
+    match _ = False
diff --git a/src/Data/Holiday/Model.hs b/src/Data/Holiday/Model.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Holiday/Model.hs
@@ -0,0 +1,91 @@
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DeriveLift #-}
+
+{-|
+Module      : Data.Holiday.Model
+Description : Holiday Model
+Copyright   : (c) Mo Kweon
+License     : MIT
+Maintainer  : kkweon@gmail.com
+Stability   : experimental
+Portability : POSIX
+
+It contains data models for Holiday
+-}
+module Data.Holiday.Model
+  ( Date(..)
+  , Holiday(..)
+  ) where
+
+import Control.Monad.Extra (liftMaybe)
+import Data.Aeson.Types (FromJSON, (.:), (.:?), parseJSON, withObject, Parser)
+import Data.List.Split (splitOn)
+import Data.Maybe (fromMaybe)
+import GHC.Generics (Generic)
+import Text.Read (readMaybe)
+import Language.Haskell.TH.Syntax (Lift)
+
+data Date
+  = YMD (Integer, Int, Int) -- ^ (Year, Month, Day) Some Holiday has a different date every year
+  | MD (Int, Int) -- ^ (Month, Day) Some holidays repeat every year on the same date
+  deriving (Show, Eq, Lift)
+
+-- | 'Holiday' represents the date of holiday and the name of holiday.
+data Holiday = Holiday
+  { date :: Date -- ^ Date of the holiday
+  , name :: String -- ^ Name of the holiday
+  , lunar :: Maybe Bool -- ^ Date maybe Lunar Date
+  } deriving (Show, Eq, Generic, Lift)
+
+instance FromJSON Holiday where
+    parseJSON =
+        withObject "Holiday" $ \v -> Holiday
+            <$> parseDate v
+            <*> v .: "name"
+            <*> v .:? "lunar"
+        where
+            parseDate o = do
+                s <- o .: "date"
+                liftMaybe $ parseKoreanDate s
+
+
+
+parseKoreanDate :: String -> Maybe Date
+parseKoreanDate xs =
+  case splitOn "-" xs of
+    [y, m, d]
+      | verifyYmd y m d -> Just $ YMD (read y, read m, read d)
+    [m, d]
+      | verifyMd m d -> Just $ MD (read m, read d)
+    _ -> Nothing
+
+verifyYmd :: String -> String -> String -> Bool
+verifyYmd y m d =
+  fromMaybe False $ do
+    year <- readMaybe y :: Maybe Integer
+    month <- readMaybe m :: Maybe Int
+    day <- readMaybe d :: Maybe Int
+    return $ isValidYear year && isValidMonth month && isValidDay day
+
+verifyMd :: String -> String -> Bool
+verifyMd m d =
+  fromMaybe False $ do
+    month <- readMaybe m :: Maybe Int
+    day <- readMaybe d :: Maybe Int
+    return $ isValidMonth month && isValidDay day
+
+isValidYear :: Integer -> Bool
+isValidYear y
+  | 1900 <= y && y <= 3000 = True
+  | otherwise = False
+
+isValidMonth :: Int -> Bool
+isValidMonth m
+  | 1 <= m && m <= 12 = True
+  | otherwise = False
+
+isValidDay :: Int -> Bool
+isValidDay d
+  | 1 <= d && d <= 31 = True
+  | otherwise = False
diff --git a/src/Util/Config.hs b/src/Util/Config.hs
new file mode 100644
--- /dev/null
+++ b/src/Util/Config.hs
@@ -0,0 +1,9 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+module Util.Config where
+
+import Data.Yaml.TH (decodeFile)
+import qualified Data.Holiday.Model as K
+
+holidays :: [K.Holiday]
+holidays = $$(decodeFile "data/ko_holidays.yaml")
diff --git a/test/Data/Holiday/KoreaSpec.hs b/test/Data/Holiday/KoreaSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Data/Holiday/KoreaSpec.hs
@@ -0,0 +1,20 @@
+module Data.Holiday.KoreaSpec where
+
+import qualified Data.Holiday.Korea as Korea
+import qualified Data.Holiday.Model as KM
+import Data.Holiday.Model (date, lunar, name)
+import Test.Hspec (Spec, describe, it, shouldBe)
+
+spec :: Spec
+spec =
+  describe "Data.Holiday.Korea" $ do
+    it "returns a SinJeong when xxxx/1/1" $
+      Korea.getHoliday 2000 1 1 `shouldBe`
+      Just
+        KM.Holiday
+          {date = KM.MD (1, 1), name = "New Year's Day", lunar = Nothing}
+    it "returns the Independence Movement Day 3/1" $
+      Korea.getHoliday 2019 3 1 `shouldBe`
+      Just
+        KM.Holiday
+          {date = KM.MD (3, 1), name = "March 1 Movement Day", lunar = Nothing}
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
