I realized selection coordinates in cb_data[“geometry”] are already in data coordinates, for a datetime axis the returned values are milliseconds since epoch. So here is a small code that displays the selection range in text:
from bokeh.plotting import Figure, output_file
from bokeh.models import CustomJS, ColumnDataSource, PreText
from bokeh.layouts import gridplot
from bokeh.resources import CDN
from bokeh.embed import file_html
import os
import datetime
wdir = os.getcwd()
start_date = datetime.datetime(2010,1,1)
date_list = [start_date + datetime.timedelta(days=x) for x in range(0,365)]
y = range(len(date_list))
TOOLS = “pan,wheel_zoom,box_zoom,undo,redo,reset,box_select,save”
fig = Figure(plot_height=400,plot_width=400,tools=TOOLS,x_axis_type=‘datetime’)
txt=PreText(text=‘Selection range:’,width=1000)
fig.tools[-2].callback = CustomJS(args=dict(txt=txt),code="""
var sel = cb_data["geometry"];
var startsec = sel["x0"]/1000;
var start = new Date(0);
start.setUTCSeconds(startsec)
var startstring = ("0" + start.getDate()).slice(-2) + "-" + ("0"+(start.getMonth()+1)).slice(-2) + "-" +start.getFullYear() + " " + ("0" + start.getHours()).slice(-2) + ":" + ("0" + start.getMinutes()).slice(-2);
var finishsec = sel["x1"]/1000;
var finish = new Date(0);
finish.setUTCSeconds(finishsec)
var finishstring = ("0" + finish.getDate()).slice(-2) + "-" + ("0"+(finish.getMonth()+1)).slice(-2) + "-" +finish.getFullYear() + " " + ("0" + finish.getHours()).slice(-2) + ":" + ("0" + finish.getMinutes()).slice(-2);
txt.text = 'Selection range from '+startstring + ' to ' + finishstring;
txt.trigger("change");
""")
fig.scatter(x=date_list,y=y)
grid = gridplot([[txt],[fig]],toolbar_location=‘left’)
outfile=open(os.path.join(wdir,‘boktest.html’),‘w’)
outfile.write(file_html(grid,CDN,‘test’))
outfile.close()
``