Disclaimer: This answer is mainly explanatory to show one (out of many) things that Python allows you to do. Also, you should probably NOT want to do things this way (the fact that you can do things doesn't mean you should)
This said, the documentation for getitem(self, key) states:
For sequence types, the accepted keys should be integers and slice
  objects.
which means that any class that wants to  mimic the behavior of a sequence type (such as a list) must be prepared to implement a __getitem__ where key can be a type slice. That (kind of) explains (or at least, is somehow related to) why in your dictionary you're getting a TypeError: unhashable type when you try to do b[slice(st,en)] = 'bla ': It's because it's trying to use the slice(st, en) instance as a dictionary key. slice objects are not hashable, and therefore, can't be used as dict keys. A dict type is NOT a sequence type, so trying to slice a dictionary has no meaning.
Let's say you have:
{
      ...    'foo': 1,
      ...    'bar': 2,
      ...    'baz': 3,
      ... }
What does it mean an slice from 'foo' to 'bar'? Would you return the set of keys in the order you entered them? ('foo', 'bar', 'baz')? Python doesn't know about that. Would it be their __hash__? That's internal, meaningless when it comes so slicing.
All this said, here's a very very bad thing... but that "works":
import datetime
class DatetimeDict(dict):
    def __getitem__(self, key):
        if isinstance(key, slice):
            sliced = {}
            start_dt = key.start
            stop_dt = key.stop
            step = key.step or 1
            internal_keys = sorted(self.keys())
            if start_dt is None:
                start_index = 0
            else:
                start_index = internal_keys.index(start_dt)
            end_index = internal_keys.index(stop_dt)
            for i in range(start_index, end_index, step):
                sliced.update({internal_keys[i]: self[internal_keys[i]]})
            return sliced
        else:
            return super(DatetimeDict, self).__getitem__(key)
    def __setitem__(self, key, val):
        return super(DatetimeDict, self).__setitem__(key, val)
a = DatetimeDict()
a[datetime.datetime.strptime('2014/01/01', '%Y/%m/%d')] = 'foo',
a[datetime.datetime.strptime('2014/01/02', '%Y/%m/%d')] = 'bar',
a[datetime.datetime.strptime('2014/01/03', '%Y/%m/%d')] = 'baz',
a[datetime.datetime.strptime('2014/01/04', '%Y/%m/%d')] = 'bla',
from_dt = datetime.datetime.strptime('2014/01/02', '%Y/%m/%d')
to_dt = datetime.datetime.strptime('2014/01/04', '%Y/%m/%d')
print a[from_dt:to_dt]
This outputs:
{
    datetime.datetime(2014, 1, 2, 0, 0): ('bar',), 
    datetime.datetime(2014, 1, 3, 0, 0): ('baz',)
}
But is bad, bad bad... DatetimeDict becomes a weird construct that is a dictionary but at the same time behaves kind of like a sequence type... Bad.
EDIT (After re-reading, I'm pretty sure I misunderstood the question)
You weren't actually trying to slice a dict, where you? The day I learn to read, I'll conquer the world... :-D
If what you want is use a range of datetimes as a dict key, I'd recommend that you just put the start and end in a tuple:
>>> import datetime
>>> st = datetime.datetime.strptime('2014/01/01', '%Y/%m/%d')
>>> en = datetime.datetime.strptime('2014/01/02', '%Y/%m/%d')
>>> key = (st, en)
>>> a = {}
>>> a[key] = 'foo'
>>> print a
{(datetime.datetime(2014, 1, 1, 0, 0), datetime.datetime(2014, 1, 2, 0, 0)): 'foo'}
Weeeelllll... at least I learned about slicing and that kind of stuff... LoL...