diff --git a/CHANGES.md b/CHANGES.md
new file mode 100644
--- /dev/null
+++ b/CHANGES.md
@@ -0,0 +1,9 @@
+# Version 0.1 (2016-12-13)
+
+  * Implemented functions
+    * slice
+    * max
+    * min
+  * Implemented CSV reader
+  * Implemented size function
+  * Implemented valueAt function
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2014 Krzysztof Langner
+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.
+
+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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,36 @@
+[![Build Status](https://travis-ci.org/klangner/time-series-lib.svg?branch=master)](https://travis-ci.org/klangner/time-series-lib)
+[![Hackage](https://img.shields.io/hackage/v/timeseries.svg)](https://hackage.haskell.org/package/timeseries)
+
+# Welcome to Haskell Time Series library
+
+Implemented functionality:
+  * Base operations on time series (get value, slice, max etc.)
+  * Reading from CSV file
+
+
+
+## Installation
+
+```sh
+stack setup
+stack build
+stack test
+```
+
+
+# Join in!
+
+We are happy to receive bug reports, fixes, documentation enhancements,
+and other improvements.
+
+Please report bugs via the
+[github issue tracker](http://github.com/klangner/time-series-lib/issues).
+
+Master [git repository](http://github.com/klangner/time-series-lib):
+
+* `git clone https://github.com/klangner/time-series-lib.git`
+
+
+# Redistributing
+
+time-series-lib source code is distributed under the BSD3 License.
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/benchmark/Benchmarks.hs b/benchmark/Benchmarks.hs
new file mode 100644
--- /dev/null
+++ b/benchmark/Benchmarks.hs
@@ -0,0 +1,28 @@
+
+import Criterion.Main
+import Data.Time (UTCTime)
+import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
+import qualified Data.TimeSeries as TS
+
+
+seriesSize :: Integer
+seriesSize = 10^6
+
+index :: Integer -> UTCTime
+index n = posixSecondsToUTCTime (fromIntegral n)
+
+lastIndex :: UTCTime
+lastIndex = index (seriesSize - 1)
+
+bigSeries :: TS.Series
+bigSeries = TS.tsSeries [1..seriesSize] [1..]
+
+
+main :: IO ()
+main = defaultMain
+    [ bgroup "Big series"
+        [ bench "size"  $ nf TS.size bigSeries
+        , bench "valueAt"  $ nf (\xs -> TS.valueAt xs lastIndex) bigSeries
+        , bench "slice"  $ nf (\xs -> TS.valueAt (TS.slice xs (index 2) lastIndex) (index 1)) bigSeries
+        ]
+    ]
diff --git a/src/Data/TimeSeries.hs b/src/Data/TimeSeries.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TimeSeries.hs
@@ -0,0 +1,9 @@
+-- | TimeSeries library
+module Data.TimeSeries
+    ( module Data.TimeSeries.Series
+    , module Data.TimeSeries.CSVReader
+    ) where
+
+
+import Data.TimeSeries.Series
+import Data.TimeSeries.CSVReader
diff --git a/src/Data/TimeSeries/CSVReader.hs b/src/Data/TimeSeries/CSVReader.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TimeSeries/CSVReader.hs
@@ -0,0 +1,37 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Data.TimeSeries.CSVReader
+    ( load
+    )where
+
+
+import qualified Data.ByteString.Lazy as BS
+import qualified Data.Text as T
+import           Data.Csv
+import qualified Data.Vector as V
+import           Data.Time (UTCTime)
+
+import           Data.TimeSeries.Series ( Series
+                                        , emptySeries
+                                        , series
+                                        )
+
+
+-- | Load data from CSV file and create Time Series from it
+-- As a first argument provide function to convert date from ByteString to UTCTime
+load :: (T.Text -> UTCTime) -> FilePath -> IO Series
+load ft filePath = do
+    csvData <- BS.readFile filePath
+    case decode HasHeader csvData of
+        Left err -> do
+            _ <- putStrLn err
+            return emptySeries
+
+        Right vs -> do
+            let vs' = V.map (parseLine ft) vs
+            return $ series (V.toList vs')
+
+
+parseLine :: (T.Text -> UTCTime) -> (T.Text, Double) -> (UTCTime, Double)
+parseLine ft (date, value) = (ft date, value)
diff --git a/src/Data/TimeSeries/Series.hs b/src/Data/TimeSeries/Series.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/TimeSeries/Series.hs
@@ -0,0 +1,107 @@
+{-# OPTIONS_GHC -funbox-strict-fields  #-}
+{-|
+Module:      Data.TimeSeries.Series
+Copyright:   (c) 2016 Krzysztof Langner
+License:     BSD3
+Stability:   experimental
+Portability: portable
+Definition and basic operation on Series.
+-}
+
+module Data.TimeSeries.Series
+    ( DataPoint
+    , Series
+    , Value
+    , emptySeries
+    , max
+    , min
+    , series
+    , size
+    , slice
+    , tsSeries
+    , valueAt
+    ) where
+
+import Prelude hiding (max, min)
+import Data.Time (UTCTime)
+import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
+
+
+type Value = Double
+data DataPoint = DP !UTCTime !Value
+                 deriving (Show, Eq)
+
+data Series = Series [DataPoint]
+    deriving (Show, Eq)
+
+
+-- | Create empty series
+emptySeries :: Series
+emptySeries = Series []
+
+
+-- | Create empty series
+series :: [(UTCTime, Double)] -> Series
+series xs = Series $ map (\(x, y) -> DP x y) xs
+
+
+-- | Create time series from timestamps and values
+--
+-- >seriesFromSeconds [1, 2, 3] [41.3, 52.22, 3.0] == Series [DP 1970-01-01 00:00:01 UTC 2.3,DP 1970-01-01 00:00:02 UTC 4.5]
+--
+tsSeries :: [Integer] -> [Value] -> Series
+tsSeries ts vs = Series (zipWith DP idx vs)
+    where idx = map (posixSecondsToUTCTime . fromIntegral) ts
+
+
+-- | Get series size.
+-- Complexity O(n)
+--
+-- >size (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) == 3
+--
+size :: Series -> Int
+size (Series xs) = length xs
+
+
+-- | Return data point value at given index
+-- Complexity O(n)
+--
+-- >valueAt (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 2 == Just 52.22
+-- >valueAt (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 5 == Nothing
+--
+valueAt :: Series -> UTCTime -> Maybe Value
+valueAt (Series xs) ts = safeHead [y | DP x y <- xs, x == ts]
+    where safeHead [] = Nothing
+          safeHead (a:_) = Just a
+
+
+-- | Return series subset
+-- Complexity O(n)
+--
+-- >slice (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 2 3 == Series [DP 2 52.22, DP 3 3.0]
+-- >slice (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 5 23 == Series []
+--
+slice :: Series -> UTCTime -> UTCTime -> Series
+slice (Series xs) start end = Series [DP x y | DP x y <- xs, x >= start && x <= end]
+
+
+-- | Return maximum value in the series
+-- Complexity O(n)
+--
+-- >max (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) == 52.22
+-- >max (Series []) == 0
+--
+max :: Series -> Value
+max (Series xs) = foldl (\d (DP _ y) -> max' d y) 0.0 xs
+    where max' a b = if a > b then a else b
+
+-- | Return maximum value in the series
+-- Complexity O(n)
+--
+-- >min (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) == 3.0
+-- >min (Series []) == 0
+--
+min :: Series -> Value
+min (Series xs) = foldl (\d (DP _ y) -> min' d y) maxValue xs
+    where min' a b = if a < b then a else b
+          maxValue = fromIntegral (maxBound :: Int)
diff --git a/test-src/Data/TimeSeries/CSVSpec.hs b/test-src/Data/TimeSeries/CSVSpec.hs
new file mode 100644
--- /dev/null
+++ b/test-src/Data/TimeSeries/CSVSpec.hs
@@ -0,0 +1,17 @@
+module Data.TimeSeries.CSVSpec (spec) where
+
+import Test.Hspec
+import Data.ByteString.Time (parseISODateTime)
+
+import qualified Data.TimeSeries as TS
+import qualified Data.TimeSeries.CSVReader as CSV
+
+
+spec :: Spec
+spec = do
+
+  describe "Reader" $ do
+
+    it "co2 test data" $ do
+        xs <- CSV.load parseISODateTime "testdata/co2.csv"
+        TS.size xs `shouldBe` 192
diff --git a/test-src/Data/TimeSeries/SeriesSpec.hs b/test-src/Data/TimeSeries/SeriesSpec.hs
new file mode 100644
--- /dev/null
+++ b/test-src/Data/TimeSeries/SeriesSpec.hs
@@ -0,0 +1,49 @@
+module Data.TimeSeries.SeriesSpec (spec) where
+
+import Test.Hspec
+import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
+
+import qualified Data.TimeSeries as TS
+
+
+spec :: Spec
+spec = do
+
+  describe "Basic operations" $ do
+
+    it "return series size" $ do
+        let idx = [1, 2, 3]
+        let values = [1.0, 2.0, 3.0]
+        TS.size (TS.tsSeries idx values) `shouldBe` 3
+
+    it "return data point value at given index" $ do
+        let idx = [10, 20, 30]
+        let values = [10.0, 12.0, 32.4]
+        let pos = posixSecondsToUTCTime $ fromIntegral 20
+        TS.valueAt (TS.tsSeries idx values) pos `shouldBe` Just 12.0
+
+    it "return Nothing value if wrong index" $ do
+        let idx = [10, 20, 30]
+        let values = [10.0, 12.0, 32.4]
+        let pos = posixSecondsToUTCTime $ fromIntegral 1234
+        TS.valueAt (TS.tsSeries idx values) pos `shouldBe` Nothing
+
+    it "return subset" $ do
+        let xs = TS.tsSeries [1..5] [10.0, 1.2, 32.4, 0.65, 11.0]
+        let start = posixSecondsToUTCTime $ fromIntegral 2
+        let end = posixSecondsToUTCTime $ fromIntegral 3
+        TS.size (TS.slice xs start end) `shouldBe` 2
+
+    it "return empty subset" $ do
+        let xs = TS.tsSeries [1..5] [10.0, 1.2, 32.4, 0.65, 11.0]
+        let start = posixSecondsToUTCTime $ fromIntegral 12
+        let end = posixSecondsToUTCTime $ fromIntegral 34
+        TS.slice xs start end `shouldBe` TS.emptySeries
+
+    it "maximum value" $ do
+        let xs = TS.tsSeries [1..5] [10.0, 1.2, 32.4, 0.65, 11.0]
+        TS.max xs `shouldBe` 32.4
+
+    it "minimum value" $ do
+        let xs = TS.tsSeries [1..5] [10.0, 1.2, 32.4, 0.65, 11.0]
+        TS.min xs `shouldBe` 0.65
diff --git a/test-src/Spec.hs b/test-src/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test-src/Spec.hs
@@ -0,0 +1,9 @@
+import Test.Hspec
+import qualified Data.TimeSeries.SeriesSpec
+import qualified Data.TimeSeries.CSVSpec
+
+
+main :: IO ()
+main = hspec $ do
+  describe "Series" Data.TimeSeries.SeriesSpec.spec
+  describe "CSV" Data.TimeSeries.CSVSpec.spec
diff --git a/testdata/co2.csv b/testdata/co2.csv
new file mode 100644
--- /dev/null
+++ b/testdata/co2.csv
@@ -0,0 +1,193 @@
+"Month","CO2 (ppm) mauna loa, 1965-1980"
+"1965-01",319.32
+"1965-02",320.36
+"1965-03",320.82
+"1965-04",322.06
+"1965-05",322.17
+"1965-06",321.95
+"1965-07",321.20
+"1965-08",318.81
+"1965-09",317.82
+"1965-10",317.37
+"1965-11",318.93
+"1965-12",319.09
+"1966-01",319.94
+"1966-02",320.98
+"1966-03",321.81
+"1966-04",323.03
+"1966-05",323.36
+"1966-06",323.11
+"1966-07",321.65
+"1966-08",319.64
+"1966-09",317.86
+"1966-10",317.25
+"1966-11",319.06
+"1966-12",320.26
+"1967-01",321.65
+"1967-02",321.81
+"1967-03",322.36
+"1967-04",323.67
+"1967-05",324.17
+"1967-06",323.39
+"1967-07",321.93
+"1967-08",320.29
+"1967-09",318.58
+"1967-10",318.60
+"1967-11",319.98
+"1967-12",321.25
+"1968-01",321.88
+"1968-02",322.47
+"1968-03",323.17
+"1968-04",324.23
+"1968-05",324.88
+"1968-06",324.75
+"1968-07",323.47
+"1968-08",321.34
+"1968-09",319.56
+"1968-10",319.45
+"1968-11",320.45
+"1968-12",321.92
+"1969-01",323.40
+"1969-02",324.21
+"1969-03",325.33
+"1969-04",326.31
+"1969-05",327.01
+"1969-06",326.24
+"1969-07",325.37
+"1969-08",323.12
+"1969-09",321.85
+"1969-10",321.31
+"1969-11",322.31
+"1969-12",323.72
+"1970-01",324.60
+"1970-02",325.57
+"1970-03",326.55
+"1970-04",327.80
+"1970-05",327.80
+"1970-06",327.54
+"1970-07",326.28
+"1970-08",324.63
+"1970-09",323.12
+"1970-10",323.11
+"1970-11",323.99
+"1970-12",325.09
+"1971-01",326.12
+"1971-02",326.61
+"1971-03",327.16
+"1971-04",327.92
+"1971-05",329.14
+"1971-06",328.80
+"1971-07",327.52
+"1971-08",325.62
+"1971-09",323.61
+"1971-10",323.80
+"1971-11",325.10
+"1971-12",326.25
+"1972-01",326.93
+"1972-02",327.83
+"1972-03",327.95
+"1972-04",329.91
+"1972-05",330.22
+"1972-06",329.25
+"1972-07",328.11
+"1972-08",326.39
+"1972-09",324.97
+"1972-10",325.32
+"1972-11",326.54
+"1972-12",327.71
+"1973-01",328.73
+"1973-02",329.69
+"1973-03",330.47
+"1973-04",331.69
+"1973-05",332.65
+"1973-06",332.24
+"1973-07",331.03
+"1973-08",329.36
+"1973-09",327.60
+"1973-10",327.29
+"1973-11",328.28
+"1973-12",328.79
+"1974-01",329.45
+"1974-02",330.89
+"1974-03",331.63
+"1974-04",332.85
+"1974-05",333.28
+"1974-06",332.47
+"1974-07",331.34
+"1974-08",329.53
+"1974-09",327.57
+"1974-10",327.57
+"1974-11",328.53
+"1974-12",329.69
+"1975-01",330.45
+"1975-02",330.97
+"1975-03",331.64
+"1975-04",332.87
+"1975-05",333.61
+"1975-06",333.55
+"1975-07",331.90
+"1975-08",330.05
+"1975-09",328.58
+"1975-10",328.31
+"1975-11",329.41
+"1975-12",330.63
+"1976-01",331.63
+"1976-02",332.46
+"1976-03",333.36
+"1976-04",334.45
+"1976-05",334.82
+"1976-06",334.32
+"1976-07",333.05
+"1976-08",330.87
+"1976-09",329.24
+"1976-10",328.87
+"1976-11",330.18
+"1976-12",331.50
+"1977-01",332.81
+"1977-02",333.23
+"1977-03",334.55
+"1977-04",335.82
+"1977-05",336.44
+"1977-06",335.99
+"1977-07",334.65
+"1977-08",332.41
+"1977-09",331.32
+"1977-10",330.73
+"1977-11",332.05
+"1977-12",333.53
+"1978-01",334.66
+"1978-02",335.07
+"1978-03",336.33
+"1978-04",337.39
+"1978-05",337.65
+"1978-06",337.57
+"1978-07",336.25
+"1978-08",334.39
+"1978-09",332.44
+"1978-10",332.25
+"1978-11",333.59
+"1978-12",334.76
+"1979-01",335.89
+"1979-02",336.44
+"1979-03",337.63
+"1979-04",338.54
+"1979-05",339.06
+"1979-06",338.95
+"1979-07",337.41
+"1979-08",335.71
+"1979-09",333.68
+"1979-10",333.69
+"1979-11",335.05
+"1979-12",336.53
+"1980-01",337.81
+"1980-02",338.16
+"1980-03",339.88
+"1980-04",340.57
+"1980-05",341.19
+"1980-06",340.87
+"1980-07",339.25
+"1980-08",337.19
+"1980-09",335.49
+"1980-10",336.63
+"1980-11",337.74
+"1980-12",338.36
diff --git a/testdata/small.csv b/testdata/small.csv
new file mode 100644
--- /dev/null
+++ b/testdata/small.csv
@@ -0,0 +1,5 @@
+"Month","CO2 (ppm) mauna loa, 1965-1980"
+"1965-01",319.32
+"1965-02",320.36
+"1965-03",320.82
+"1965-04",322.06
diff --git a/timeseries.cabal b/timeseries.cabal
new file mode 100644
--- /dev/null
+++ b/timeseries.cabal
@@ -0,0 +1,68 @@
+name:           timeseries
+version:        0.1.0
+synopsis:       Library for Time Series processing
+License:        BSD3
+License-file:   LICENSE
+Copyright:      (c) 2016 Krzysztof Langner
+Extra-Source-Files:
+                README.md,
+                CHANGES.md,
+                LICENSE,
+                benchmark/*.hs,
+                testdata/*.csv
+description:
+    Library for processing time series data.
+
+homepage:       https://github.com/klangner/timeseries
+author:         Krzysztof Langner
+maintainer:     klangner@gmail.com
+category:       Data
+build-type:     Simple
+cabal-version:  >=1.10
+
+source-repository head
+  type:     git
+  location: https://github.com/klangner/timeseries
+
+library
+  hs-source-dirs:   src
+  default-language: Haskell2010
+  ghc-options:      -Wall
+  build-depends:
+                    base >= 4.7 && < 5,
+                    bytestring < 0.11,
+                    bytestring-time < 1,
+                    cassava >= 0.4 && < 0.5,
+                    text < 2,
+                    time >= 1.5 && < 2,
+                    vector < 0.12
+  exposed-modules:
+                    Data.TimeSeries
+  other-modules:
+                    Data.TimeSeries.Series,
+                    Data.TimeSeries.CSVReader
+
+test-suite unit-tests
+  type:             exitcode-stdio-1.0
+  main-is:          Spec.hs
+  default-language: Haskell2010
+  build-depends:
+                    base >= 4 && <5,
+                    Cabal <2,
+                    hspec >=2 && <3,
+                    QuickCheck >=2.6 && <3,
+                    bytestring < 0.11,
+                    bytestring-time < 1,
+                    cassava >= 0.4 && < 0.5,
+                    text < 2,
+                    time >= 1.5 && < 2,
+                    vector < 0.12
+  other-modules:
+                    Data.TimeSeries,
+                    Data.TimeSeries.Series,
+                    Data.TimeSeries.SeriesSpec
+                    Data.TimeSeries.CSVReader
+                    Data.TimeSeries.CSVSpec
+  hs-source-dirs:
+                    src,
+                    test-src
