+Accessing original values
+-------------------------
+
+To access the saved state of the Task, use dict-like access using the
+``original`` attribute:
+
+ >>> t = Task(tw, description="tidy up")
+ >>> t.save()
+ >>> t['description'] = "tidy up the kitchen and bathroom"
+ >>> t['description']
+ "tidy up the kitchen and bathroom"
+ >>> t.original['description']
+ "tidy up"
+
+When you save the task, original values are refreshed to reflect the
+saved state of the task:
+
+ >>> t.save()
+ >>> t.original['description']
+ "tidy up the kitchen and bathroom"
+
+Dealing with dates and time
+---------------------------
+
+Any timestamp-like attributes of the tasks are converted to timezone-aware
+datetime objects. To achieve this, Tasklib leverages ``pytz`` Python module,
+which brings the Olsen timezone databaze to Python.
+
+This shields you from annoying details of Daylight Saving Time shifts
+or conversion between different timezones. For example, to list all the
+tasks which are due midnight if you're currently in Berlin:
+
+ >>> myzone = pytz.timezone('Europe/Berlin')
+ >>> midnight = myzone.localize(datetime(2015,2,2,0,0,0))
+ >>> tw.tasks.filter(due__before=midnight)
+
+However, this is still a little bit tedious. That's why TaskWarrior object
+is capable of automatic timezone detection, using the ``tzlocal`` Python
+module. If your system timezone is set to 'Europe/Berlin', following example
+will work the same way as the previous one:
+
+ >>> tw.tasks.filter(due__before=datetime(2015,2,2,0,0,0))
+
+You can also use simple dates when filtering:
+
+ >>> tw.tasks.filter(due__before=date(2015,2,2))
+
+In such case, a 00:00:00 is used as the time component.
+
+Of course, you can use datetime naive objects when initializing Task object
+or assigning values to datetime atrributes:
+
+ >>> t = Task(tw, description="Buy new shoes", due=date(2015,2,5))
+ >>> t['due']
+ datetime.datetime(2015, 2, 5, 0, 0, tzinfo=<DstTzInfo 'Europe/Berlin' CET+1:00:00 STD>)
+ >>> t['due'] = date(2015,2,6,15,15,15)
+ >>> t['due']
+ datetime.datetime(2015, 2, 6, 15, 15, 15, tzinfo=<DstTzInfo 'Europe/Berlin' CET+1:00:00 STD>)
+
+However, since timezone-aware and timezone-naive datetimes are not comparable
+in Python, this can cause some unexpected behaviour:
+
+ >>> from datetime import datetime
+ >>> now = datetime.now()
+ >>> t = Task(tw, description="take out the trash now")
+ >>> t['due'] = now
+ >>> now
+ datetime.datetime(2015, 2, 1, 19, 44, 4, 770001)
+ >>> t['due']
+ datetime.datetime(2015, 2, 1, 19, 44, 4, 770001, tzinfo=<DstTzInfo 'Europe/Berlin' CET+1:00:00 STD>)
+ >>> t['due'] == now
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ TypeError: can't compare offset-naive and offset-aware datetimes
+
+If you want to compare datetime aware value with datetime naive value, you need
+to localize the naive value first:
+
+ >>> from datetime import datetime
+ >>> from tasklib.task import local_zone
+ >>> now = local_zone.localize(datetime.now())
+ >>> t['due'] = now
+ >>> now
+ datetime.datetime(2015, 2, 1, 19, 44, 4, 770001, tzinfo=<DstTzInfo 'Europe/Berlin' CET+1:00:00 STD>)
+ >>> t['due'] == now
+ True
+
+Also, note that it does not matter whether the timezone aware datetime objects
+are set in the same timezone:
+
+ >>> import pytz
+ >>> t['due']
+ datetime.datetime(2015, 2, 1, 19, 44, 4, 770001, tzinfo=<DstTzInfo 'Europe/Berlin' CET+1:00:00 STD>)
+ >>> now.astimezone(pytz.utc)
+ datetime.datetime(2015, 2, 1, 18, 44, 4, 770001, tzinfo=<UTC>)
+ >>> t['due'] == now.astimezone(pytz.utc)
+ True
+
+*Note*: Following behaviour is available only for TaskWarrior >= 2.4.0.
+
+There is a third approach to setting up date time values, which leverages
+the 'task calc' command. You can simply set any datetime attribute to
+any string that contains an acceptable TaskWarrior-formatted time expression::
+
+ $ task calc now + 1d
+ 2015-07-17T21:17:54
+
+This syntax can be leveraged in the python interpreter as follows::
+
+ >>> t['due'] = "now + 1d"
+ >>> t['due']
+ datetime.datetime(2015, 7, 17, 21, 19, 31, tzinfo=<DstTzInfo 'Europe/Berlin' CEST+2:00:00 DST>)
+
+It can be easily seen that the string with TaskWarrior-formatted time expression
+is automatically converted to native datetime in the local time zone.
+
+For the list of acceptable formats and keywords, please consult:
+
+* http://taskwarrior.org/docs/dates.html
+* http://taskwarrior.org/docs/named_dates.html
+
+However, as each such assigment involves call to 'task calc' for conversion,
+it might cause some performance issues when assigning strings to datetime
+attributes repeatedly, in a automated manner.
+
+Working with annotations
+------------------------
+
+Annotations of the tasks are represented in tasklib by ``TaskAnnotation`` objects. These
+are much like ``Task`` objects, albeit very simplified.
+
+ >>> annotated_task = tw.tasks.get(description='Annotated task')
+ >>> annotated_task['annotations']
+ [Yeah, I am annotated!]
+
+Annotations have only defined ``entry`` and ``description`` values::
+
+ >>> annotation = annotated_task['annotations'][0]
+ >>> annotation['entry']
+ datetime.datetime(2015, 1, 3, 21, 13, 55, tzinfo=<DstTzInfo 'Europe/Berlin' CET+1:00:00 STD>)
+ >>> annotation['description']
+ u'Yeah, I am annotated!'
+
+To add a annotation to a Task, use ``add_annotation()``::
+
+ >>> task = Task(tw, description="new task")
+ >>> task.add_annotation("we can annotate any task")
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "build/bdist.linux-x86_64/egg/tasklib/task.py", line 355, in add_annotation
+ tasklib.task.NotSaved: Task needs to be saved to add annotation
+
+However, Task needs to be saved before you can add a annotation to it::