diff --git a/README.md b/README.md
index c71f28c4f4960f2d978553ea75db83d72c65acf0..479fe21a33daea70a560597572829a1bad2f52bd 100644
--- a/README.md
+++ b/README.md
@@ -134,3 +134,8 @@ Or you can check for strict inclusion
 Range('<-1;1>') in Range('<-2;2>')
 ```
 
+## TimeProviders
+
+**EXPERIMENTAL**
+
+Can be imported from _sai.timeproviders_.
diff --git a/firanka/series.py b/firanka/series.py
index c1bb0cc140d1d7c6f4210b38ce31a9e983c32a5f..606a187686a004011b739c4e6e234664f1533e8c 100644
--- a/firanka/series.py
+++ b/firanka/series.py
@@ -13,6 +13,8 @@ __all__ = [
     'DiscreteSeries',
     'ModuloSeries',
     'Series',
+    'SCALAR_LINEAR_INTERPOLATOR',
+    'LinearInterpolationSeries',
 ]
 
 
@@ -314,3 +316,44 @@ class ModuloSeries(Series):
             item = 0
 
         return self.series._get_for(self.series.domain.start + item)
+
+
+def SCALAR_LINEAR_INTERPOLATOR(t0, v0, t1, v1, tt):
+    """
+    Good intepolator if our values can be added, subtracted, multiplied and divided
+    """
+    return v0 + (tt-t0) * (t1-t0)/(v1-v0)
+
+
+class LinearInterpolationSeries(DiscreteSeries):
+
+    def __init__(self, data, domain=None,
+                 interpolator=lambda t0, v0, t1, v1, tt: v0
+                 , *args, **kwargs):
+        """
+        :param interpolator: callable(t0: float, v0: any, t1: float, v1: any, tt: float) -> any
+            This, given intepolation points (t0, v0) and (t1, v1) such that t0 <= tt <= t1,
+            return a value for index tt
+        """
+        self.interpolator = interpolator
+        if isinstance(data, DiscreteSeries):
+            self.data = data.data
+            self.domain = domain or data.domain
+        else:
+            super(LinearInterpolationSeries, self).__init__(data, domain, *args, **kwargs)
+
+    def _get_for(self, item):
+        if item == self.domain.start:
+            return self.data[0][1]
+
+        if len(self.data) == 1:
+            return super(LinearInterpolationSeries, self).__getitem__(item)
+
+        for i in six.moves.range(0, len(self.data)-1):
+            cur_i, cur_v = self.data[i]
+            next_i, next_v = self.data[i+1]
+
+            if cur_i <= item <= next_i:
+                return self.interpolator(cur_i, cur_v, next_i, next_v, item)
+
+        return self.data[-1][1]
diff --git a/tests/test_series.py b/tests/test_series.py
index 8b8a0221fd20a967034bdcc9458c60ad4bd5fe12..c5396638282e8557832ba5d2ab07222363dcf1b0 100644
--- a/tests/test_series.py
+++ b/tests/test_series.py
@@ -3,7 +3,8 @@ from __future__ import print_function, absolute_import, division
 import six
 import math
 import unittest
-from firanka.series import DiscreteSeries, FunctionSeries, ModuloSeries
+from firanka.series import DiscreteSeries, FunctionSeries, ModuloSeries, \
+    LinearInterpolationSeries, SCALAR_LINEAR_INTERPOLATOR
 from firanka.ranges import Range
 from firanka.exceptions import NotInDomainError
 
@@ -174,3 +175,16 @@ class TestModuloSeries(unittest.TestCase):
         ser2 = FunctionSeries(NOOP, '<0;3)')
 
         ser3 = ser1.join(ser2, lambda x, y: x * y)
+
+
+class TestLinearInterpolation(unittest.TestCase):
+    def test_lin(self):
+        series = LinearInterpolationSeries(
+            DiscreteSeries([(0, 1), (1, 2), (2, 3)], '<0;3)'),
+            None, SCALAR_LINEAR_INTERPOLATOR)
+
+        self.assertEqual(series[0], 1)
+        self.assertEqual(series[0.5], 1.5)
+        self.assertEqual(series[1], 2)
+        self.assertEqual(series[2.3], 3)
+