diff --git a/gracedb/templatetags/timeutil.py b/gracedb/templatetags/timeutil.py index 07f1827cd4a3259796b540092b24d8a91150e334..ed868f86977315539c274b35d3f9f2fef71f165c 100644 --- a/gracedb/templatetags/timeutil.py +++ b/gracedb/templatetags/timeutil.py @@ -3,26 +3,110 @@ from django import template from django.conf import settings from django.utils import dateformat +from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe + + import pytz +import time +import datetime # DATETIME_SETTINGS is guaranteed to be set. GRACE_DATETIME_FORMAT is not. FORMAT = getattr(settings, 'GRACE_DATETIME_FORMAT', settings.DATETIME_FORMAT) -LOCAL_TZ = pytz.timezone(settings.TIME_ZONE) +SERVER_TZ = pytz.timezone(settings.TIME_ZONE) -register = template.Library() +LLO_TZ = pytz.timezone("America/Chicago") +LHO_TZ = pytz.timezone("America/Los_Angeles") +VIRGO_TZ = pytz.timezone("Europe/Rome") -@register.filter(name='utc') -def utc(dt, format=FORMAT): - if not dt.tzinfo: - dt = LOCAL_TZ.localize(dt) - dt = dt.astimezone(pytz.utc) - return dateformat.format(dt, format) +register = template.Library() -@register.filter(name='gpsdate') +# OK. What we're trying to do here is, +# given a time in some time system, gps, posix, datetime, whatever, +# produce something that will render in a desired manner and will +# be javascript-convertible to other formats/timezones/what-have-you. +# +# So... these filters, which are named after their timekeeping system, +# will convert from that time system, to ... +# <time value="POSIX TIME VALUE" [label="LABEL"]>FORMATTED TIME</time> + +@register.filter +def multiTime(t, label, autoescape=None): + format = FORMAT + + if autoescape: + esc = conditional_escape + else: + esc = lambda x: x + + if label is not None: + label_attr = ' name="time-%s"' % esc(label) + else: + label_attr = "" + + if isinstance(t, datetime.datetime): + dt = t + if not dt.tzinfo: + dt = SERVER_TZ.localize(dt) + dt = dt.astimezone(pytz.utc) + posix_time = time.mktime(dt.timetuple()) + gps_time = int(posixToGpsTime(posix_time)) + elif isinstance(t, int) or isinstance(t, long): + gps_time = t + dt = gpsToUtc(t) + posix_time = time.mktime(dt.timetuple()) + else: + raise ValueError("time must be type int, long or datetime, not '%s'" % type(t)) + + # JavaScript -- parsable by Date() object constructor + # "Jan 2, 1985 00:00:00 UTC" + js_parsable_time = esc(dateformat.format(dt, "F j, Y h:i:s")+" UTC") + + lho_time = esc(dateformat.format(dt.astimezone(LHO_TZ), format)) + llo_time = esc(dateformat.format(dt.astimezone(LLO_TZ), format)) + virgo_time = esc(dateformat.format(dt.astimezone(VIRGO_TZ), format)) + utc_time = esc(dateformat.format(dt, format)) + + if isinstance(t, datetime.datetime): + display_time = utc_time + else: + display_time = gps_time + + rv = '<time utc="%s" gps="%s" llo="%s" lho="%s" virgo="%s" jsparsable="%s"%s>%s</time>' % \ + (utc_time, gps_time, llo_time, lho_time, virgo_time, js_parsable_time, label_attr, display_time) + + return mark_safe(rv) +multiTime.needs_autoescape = True + + +@register.filter +def timeselect(label, default, autoescape=None): + if autoescape: + esc = conditional_escape + else: + esc = lambda x: x + rv = """<form><select onChange="changeTime(this, '%s')">""" % esc(label) + for value, displayname in [ + ("gps", "GPS Time"), + ("llo", "LLO Local"), + ("lho", "LHO Local"), + ("virgo", "Virgo Time"), + ("utc", "UTC"),]: + selected = "" + if value == default: + selected = " SELECTED" + rv += '<option value="%s"%s>%s</option>' % (esc(value), selected, esc(displayname)) + rv += "</select></form>" + return mark_safe(rv) +timeselect.needs_autoescape = True + +@register.filter def gpsdate(gpstime, format=FORMAT): - return dateformat.format(gpsToUTC(gpstime), format) + return dateformat.format(gpsToUtc(gpstime), format) + +# TAG that generates stuff that changes time display what-nots. # GPS time conversion @@ -30,6 +114,7 @@ def gpsdate(gpstime, format=FORMAT): # This is kind of awful in that leapSeconds # are hard coded and needs to be kept up to date. # Also, this should be somewhere else. +# Also, there are almost certainly failing edge cases at leap second adjustment times. import calendar, datetime @@ -60,6 +145,15 @@ def gpsToPosixTime(gpsTime): t = t - 1 return t -def gpsToUTC(gpsTime): +def posixToGpsTime(posixTime): + change = 0 + for leap in leapSeconds: + if posixTime > leap: + change += 1 + return posixTime + change - gpsEpoch + +def gpsToUtc(gpsTime): t = gpsToPosixTime(gpsTime) return datetime.datetime.fromtimestamp(t, pytz.utc) + + diff --git a/templates/base.html b/templates/base.html index e4762cb093cc2ca570595877c7eb194a137ec49c..551c3140478f9089ee4b0af8d680229aa1b199c0 100644 --- a/templates/base.html +++ b/templates/base.html @@ -4,6 +4,19 @@ <head> <link rel="stylesheet" href="/gracedb-static/css/style.css" /> <title>GraceDb | {% block title %}{% endblock %}</title> +<!-- START TESTING --> +<script type="text/javascript"> +function changeTime(obj, label) { + var timetype= obj[obj.selectedIndex].value; + if (timetype=="") { return; } + var times = document.getElementsByName("time-"+label); + for (i=0; i<times.length; i++) { + newtime = times[i].getAttribute(timetype); + times[i].innerHTML = newtime; + } +} +</script> +<!-- END TESTING --> </head> <body id="{% block pageid %}{% endblock %}"> diff --git a/templates/gracedb/event_detail.html b/templates/gracedb/event_detail.html index c6e8983fa8f1e5f9d79f597b4358d702bb0952bb..6ad9d497284499bfa39c98e31e315787b1798b62 100644 --- a/templates/gracedb/event_detail.html +++ b/templates/gracedb/event_detail.html @@ -12,8 +12,10 @@ <tr><th>Group</th><td>{{ object.group.name }}</td></tr> <tr><th>Type</th><td>{{ object.get_analysisType_display }}</td></tr> {% if object.gpstime %} - <tr><th>GPS Time</th><td> - <span title="{{ object.gpstime|gpsdate }}">{{ object.gpstime }}</span></td></tr> + <tr><th>Event Time {{ "gps"|timeselect:"gps" }}</th> + <!-- <td><span title="{{ object.gpstime|gpsdate }}">{{ object.gpstime }}</span></td> --> + <td>{{ object.gpstime|multiTime:"gps" }}</td> + </tr> {% endif %} <tr><th>Data</th><td> <a href="{{ object.weburl }}">{{ object.weburl }}</a> @@ -22,7 +24,7 @@ <a href="{{ object.wikiurl }}">{{ object.wikiurl }}</a> </td></tr> <tr><th>Sumitter</th><td>{{ object.submitter.name }}</td></tr> - <tr><th>Created</th><td>{{ object.created|utc }} + <tr><th>Created{{ "created"|timeselect:"utc" }}</th><td>{{ object.created|multiTime:"created" }} </td></tr> </table> @@ -30,14 +32,14 @@ <h3>Log Entries:</h3> <table> <tr> - <th>Date</th> + <th>Date {{ "logtime"|timeselect:"utc" }}</th> <th>Submitter</th> <th>File</th> <th>Comment</th> </tr> {% for log in object.eventlog_set.iterator %} <tr class={% cycle 'odd' 'even' %}> - <td>{{ log.created|utc }}</td> + <td>{{ log.created|multiTime:"logtime" }}</td> <td>{{ log.issuer }}</td> <td><a href="{{ log.fileurl }}">{{ log.filename }}</a></td> <td>{{ log.comment }}</td> diff --git a/templates/gracedb/event_list.html b/templates/gracedb/event_list.html index 5bdac7bed938cee8e02d1f72c765a517e8e3d3ae..becca4235c4237996e9f225d4f0fc2b3de9e0046 100644 --- a/templates/gracedb/event_list.html +++ b/templates/gracedb/event_list.html @@ -19,7 +19,7 @@ <th>Submitter</th> <th>Group</th> <th>Type</th> - <th>GPS Time</th> + <th>Event Time {{ "gps"|timeselect:"gps" }}</th> <th>Web</th> <th>Wiki</th> </tr> @@ -49,7 +49,8 @@ <td>{{ obj.group }} </td> <td>{{ obj.get_analysisType_display }} </td> <td>{% if obj.gpstime%} - <span title="{{ obj.gpstime|gpsdate }}">{{ obj.gpstime }}</span> + <!-- <span title="{{ obj.gpstime|gpsdate }}">{{ obj.gpstime }}</span> --> + {{ obj.gpstime|multiTime:"gps" }} {% endif %}</td> <td><a href="{{ obj.weburl }}">Web: {{ obj.graceid }}</a></td> <td><a href="{{ obj.wikiurl }}">Wiki: {{ obj.graceid }}</a></td>