diff --git a/Data/Dates.hs b/Data/Dates.hs
new file mode 100644
--- /dev/null
+++ b/Data/Dates.hs
@@ -0,0 +1,332 @@
+{-# LANGUAGE UnicodeSyntax, DeriveDataTypeable #-}
+-- | Operations with dates
+module Data.Dates
+  (DateTime (..),
+   Time (..),
+   parseDate,
+   pDate,
+   getCurrentDateTime
+  ) where
+
+import Prelude.Unicode
+import Data.Char (toUpper)
+import Data.List
+import Data.Time.Calendar
+import Data.Time.LocalTime
+import Text.Parsec
+import Text.Parsec.String
+import Data.Generics
+
+-- | Date / Time
+data DateTime =
+  DateTime {
+    year ∷ Int,
+    month ∷ Int,
+    day ∷ Int,
+    hour ∷ Int,
+    minute ∷ Int,
+    second ∷ Int }
+  deriving (Eq,Ord,Data,Typeable)
+
+-- | 12 months names.
+months ∷ [String]
+months = ["january",
+          "february",
+          "march",
+          "april",
+          "may",
+          "june",
+          "july",
+          "august",
+          "september",
+          "october",
+          "november",
+          "december"]
+
+-- | capitalize first letter of the string
+capitalize ∷ String → String
+capitalize [] = []
+capitalize (x:xs) = (toUpper x):xs
+
+-- | Show name of given month
+showMonth ∷  Int → String
+showMonth i = capitalize $ months !! (i-1)
+
+instance Show DateTime where
+  show (DateTime y m d h mins s) = 
+    show d ⧺ " " ⧺ showMonth m ⧺ " " ⧺ show y ⧺ ", " ⧺
+      show h ⧺ ":" ⧺ show mins ⧺ ":" ⧺ show s
+
+-- | Only time, without date
+data Time = 
+  Time {
+    tHour ∷ Int,
+    tMinute ∷ Int,
+    tSecond ∷ Int }
+  deriving (Eq,Ord,Show,Data,Typeable)
+
+-- | Get current date and time.
+getCurrentDateTime ∷  IO DateTime
+getCurrentDateTime = do
+  zt ← getZonedTime
+  let lt = zonedTimeToLocalTime zt
+      ld = localDay lt
+      ltod = localTimeOfDay lt
+      (y,m,d) = toGregorian ld
+      h = todHour ltod
+      mins = todMin ltod
+      s = round $ todSec ltod
+  return $ DateTime (fromIntegral y) m d h mins s
+
+uppercase ∷ String → String
+uppercase = map toUpper
+
+isPrefixOfI ∷  String → String → Bool
+p `isPrefixOfI` s = (uppercase p) `isPrefixOf` (uppercase s)
+
+lookupS ∷ String → [(String,a)] → Maybe a
+lookupS _ [] = Nothing
+lookupS k ((k',v):other) | k `isPrefixOfI` k' = Just v
+                         | otherwise          = lookupS k other
+
+monthsN ∷ [(String,Int)]
+monthsN = zip months [1..]
+
+lookupMonth ∷ String → Maybe Int
+lookupMonth n = lookupS n monthsN
+
+date ∷  Int → Int → Int → DateTime
+date y m d = DateTime y m d 0 0 0
+
+addTime ∷  DateTime → Time → DateTime
+addTime dt t = dt {
+                 hour = tHour t + hour dt,
+                 minute = tMinute t + minute dt,
+                 second = tSecond t + second dt }
+
+times ∷ Int → Parser t → Parser [t]
+times 0 _ = return []
+times n p = do
+  ts ← times (n-1) p
+  t ← optionMaybe p
+  case t of
+    Just t' → return (ts ++ [t'])
+    Nothing → return ts
+                               
+number ∷ Int → Int → Parser Int
+number n m = do
+  t ← read `fmap` (n `times` digit)
+  if t > m
+    then fail "number too large"
+    else return t
+
+pYear ∷ Parser Int
+pYear = do
+  y ← number 4 10000
+  if y < 2000
+    then return (y+2000)
+    else return y
+
+pMonth ∷ Parser Int
+pMonth = number 2 12
+
+pDay ∷ Parser Int
+pDay = number 2 31
+
+euroNumDate ∷ Parser DateTime
+euroNumDate = do
+  d ← pDay
+  char '.'
+  m ← pMonth
+  char '.'
+  y ← pYear
+  return $ date y m d
+
+americanDate ∷ Parser DateTime
+americanDate = do
+  y ← pYear
+  char '/'
+  m ← pMonth
+  char '/'
+  d ← pDay
+  return $ date y m d
+
+euroNumDate' ∷ Int → Parser DateTime
+euroNumDate' year = do
+  d ← pDay
+  char '.'
+  m ← pMonth
+  return $ date year m d
+
+americanDate' ∷ Int → Parser DateTime
+americanDate' year = do
+  m ← pMonth
+  char '/'
+  d ← pDay
+  return $ date year m d
+
+strDate ∷ Parser DateTime
+strDate = do
+  d ← pDay
+  space
+  ms ← many1 letter
+  case lookupMonth ms of
+    Nothing → fail $ "unknown month: "++ms
+    Just m  → do
+      space
+      y ← pYear
+      notFollowedBy $ char ':'
+      return $ date y m d
+
+strDate' ∷ Int → Parser DateTime
+strDate' year = do
+  d ← pDay
+  space
+  ms ← many1 letter
+  case lookupMonth ms of
+    Nothing → fail $ "unknown month: "++ms
+    Just m  → return $ date year m d
+
+time24 ∷ Parser Time
+time24 = do
+  h ← number 2 23
+  char ':'
+  m ← number 2 59
+  x ← optionMaybe $ char ':'
+  case x of
+    Nothing → return $ Time h m 0
+    Just _ → do
+      s ← number 2 59
+      notFollowedBy letter
+      return $ Time h m s
+
+ampm ∷ Parser Int
+ampm = do
+  s ← many1 letter
+  case map toUpper s of
+    "AM" → return 0
+    "PM" → return 12
+    _ → fail "AM/PM expected"
+
+time12 ∷ Parser Time
+time12 = do
+  h ← number 2 12
+  char ':'
+  m ← number 2 59
+  x ← optionMaybe $ char ':'
+  s ← case x of
+            Nothing → return 0
+            Just _  → number 2 59
+  optional space
+  hd ← ampm
+  return $ Time (h+hd) m s
+
+pAbsDate ∷ Int → Parser DateTime
+pAbsDate year = do
+  date ← choice $ map try $ map ($ year) $ [
+                              const euroNumDate,
+                              const americanDate,
+                              const strDate,
+                              strDate',
+                              euroNumDate',
+                              americanDate']
+  optional $ char ','
+  s ← optionMaybe space
+  case s of
+    Nothing → return date
+    Just _ → do
+      t ← choice $ map try [time12,time24]
+      return $ date `addTime` t
+
+data DateIntervalType = Day | Week | Month | Year
+  deriving (Eq,Show,Read)
+
+data DateInterval = Days ℤ
+                  | Weeks ℤ
+                  | Months ℤ
+                  | Years ℤ
+  deriving (Eq,Show)
+
+convertTo ∷  DateTime → Day
+convertTo dt = fromGregorian (fromIntegral $ year dt) (month dt) (day dt)
+
+convertFrom ∷  Day → DateTime
+convertFrom dt = 
+  let (y,m,d) = toGregorian dt
+  in  date (fromIntegral y) m d
+
+modifyDate ∷  (t → Day → Day) → t → DateTime → DateTime
+modifyDate fn x dt = convertFrom $ fn x $ convertTo dt
+
+addInterval ∷  DateTime → DateInterval → DateTime
+addInterval dt (Days ds) = modifyDate addDays ds dt
+addInterval dt (Weeks ws) = modifyDate addDays (ws*7) dt
+addInterval dt (Months ms) = modifyDate addGregorianMonthsClip ms dt
+addInterval dt (Years ys) = modifyDate addGregorianYearsClip ys dt
+
+maybePlural ∷ String → Parser String
+maybePlural str = do
+  r ← string str
+  optional $ char 's'
+  return (capitalize r)
+
+pDateInterval ∷ Parser DateIntervalType
+pDateInterval = do
+  s ← choice $ map maybePlural ["day", "week", "month", "year"]
+  return $ read s
+
+pRelDate ∷ DateTime → Parser DateTime
+pRelDate date = do
+  offs ← (try futureDate) <|> (try passDate) <|> (try today) <|> (try tomorrow) <|> yesterday
+  return $ date `addInterval` offs
+
+futureDate ∷ Parser DateInterval
+futureDate = do
+  string "in "
+  n ← many1 digit
+  char ' '
+  tp ← pDateInterval
+  case tp of
+    Day →   return $ Days (read n)
+    Week →  return $ Weeks (read n)
+    Month → return $ Months (read n)
+    Year →  return $ Years (read n)
+
+passDate ∷ Parser DateInterval
+passDate = do
+  n ← many1 digit
+  char ' '
+  tp ← pDateInterval
+  string " ago"
+  case tp of
+    Day →   return $ Days $ - (read n)
+    Week →  return $ Weeks $ - (read n)
+    Month → return $ Months $ - (read n)
+    Year →  return $ Years $ - (read n)
+
+today ∷ Parser DateInterval
+today = do
+  string "today"
+  return $ Days 0
+
+tomorrow ∷ Parser DateInterval
+tomorrow = do
+  string "tomorrow"
+  return $ Days 1
+
+yesterday ∷ Parser DateInterval
+yesterday = do
+  string "yesterday"
+  return $ Days (-1)
+
+-- | Parsec parser for DateTime.
+pDate ∷ DateTime       -- ^ Current date / time, to use as base for relative dates
+      → Parser DateTime
+pDate date =  (try $ pRelDate date) <|> (try $ pAbsDate $ year date)
+
+-- | Parse date/time
+parseDate ∷ DateTime  -- ^ Current date / time, to use as base for relative dates
+          → String    -- ^ String to parse
+          → Either ParseError DateTime
+parseDate date s = runParser (pDate date) () "" s
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2012, IlyaPortnov
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of IlyaPortnov nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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/dates.cabal b/dates.cabal
new file mode 100644
--- /dev/null
+++ b/dates.cabal
@@ -0,0 +1,42 @@
+name:                dates
+version:             0.1.0.0
+synopsis:            Small library for parsing different dates formats.
+description:         This package allows to parse many different formats
+                     of dates. Both absolute and relative dates are supported.
+                     Supported date formats are:
+                     .
+                       * DD.MM.YYYY
+                       .
+                       * YYYY\/MM\/DD
+                       .
+                       * `12 September 2012'
+                       .
+                       * `today', `tomorrow', `yesterday'
+                       .
+                       * `in 2 days', '3 weeks ago'
+                     .
+                     4-digits years may be abbreviated (such as 12 for 2012).
+                     Both 12-hour and 24-hour time formats are supported.
+
+homepage:            http://redmine.iportnov.ru/projects/dates/
+license:             BSD3
+license-file:        LICENSE
+author:              IlyaPortnov
+maintainer:          portnov84@rambler.ru
+-- copyright:           
+category:            Data
+build-type:          Simple
+cabal-version:       >=1.8
+
+library
+  exposed-modules:     Data.Dates
+  -- other-modules:       
+  build-depends:       base ==4.5.*,
+                       base-unicode-symbols ==0.2.*,
+                       time ==1.4.*,
+                       parsec ==3.1.*,
+                       syb ==0.3.*
+
+Source-repository head
+  type:     git
+  location: git://redmine.iportnov.ru/dates.git
