Repository: bokeh/bokeh

Issue:
Span location cannot accept datetime whereas Labels can deal with it.
OK I hope this is an easy one. I'm working with spans and labels for the spans and I see that the Span object requires an Integer location meaning you have to do a little bit of conversion to your datetime data whereas Labels can accept a datetime object directly for the x argument and automatically converts it to microseconds since epoch. So when I make a span and a label for the span next to it, I'm coding the x-axis location differently (saving a bit of code by not converting the location for the Label)

Since the formulation for automatic conversion of datetimes to integer exists for Labels, it would be nice to use the same thing for Span's and thus relax the integer type requirement for the location argument.


Discussion:
@jasonsross This is an easy one, tho the few core devs are underwater with other tasks right now, so perhaps you can work up a PR? 

You need to add a `.accepts` clause to the `location` property of `Span` here:

https://github.com/bokeh/bokeh/blob/master/bokeh/models/annotations.py#L850-L852

You can find a model of exactly the kind of change necessary here on `Label`:

https://github.com/bokeh/bokeh/blob/master/bokeh/models/annotations.py#L588

As a bonus, both `Label` and `Span` could use a short test to verify that the datetime conversion happens, which would help ensure there are no future regressions.  Here is the test file for annotations:

https://github.com/bokeh/bokeh/blob/master/bokeh/models/tests/test_annotations.py

Resolving patch:
diff --git a/bokeh/models/annotations.py b/bokeh/models/annotations.py
--- a/bokeh/models/annotations.py
+++ b/bokeh/models/annotations.py
@@ -849,7 +849,10 @@ class Span(Annotation):
 
     location = Float(help="""
     The location of the span, along ``dimension``.
-    """)
+
+    Datetime values are also accepted, but note that they are immediately
+    converted to milliseconds-since-epoch.
+    """).accepts(Datetime, convert_datetime_type)
 
     location_units = Enum(SpatialUnits, default='data', help="""
     The unit type for the location attribute. Interpreted as "data space"


Test patch:
diff --git a/bokeh/models/tests/test_annotations.py b/bokeh/models/tests/test_annotations.py
--- a/bokeh/models/tests/test_annotations.py
+++ b/bokeh/models/tests/test_annotations.py
@@ -1,5 +1,6 @@
 from __future__ import absolute_import
 import mock
+from datetime import datetime
 
 from bokeh.core.properties import field, value
 from bokeh.core.validation import check_integrity
@@ -253,6 +254,11 @@ def test_Label():
         prefix('border_', LINE),
         prefix('background_', FILL))
 
+def test_Label_accepts_datetime_xy():
+    obj = Label(x = datetime(2018,8,7,0,0),
+                y = datetime(2018,8,7,0,0))
+    assert obj.x == 1533600000000.0
+    assert obj.y == 1533600000000.0
 
 def test_LabelSet():
     label_set = LabelSet()
@@ -340,6 +346,9 @@ def test_Span():
         "render_mode"
     ], LINE)
 
+def test_Span_accepts_datetime_location():
+    obj = Span(location = datetime(2018,8,7,0,0))
+    assert obj.location == 1533600000000.0
 
 def test_Title():
     title = Title()