1#!/usr/bin/env python3
  2
  3"""Web based time conversions."""
  4
  5import logging
  6from datetime import datetime
  7
  8from django.shortcuts import render
  9from django.http import HttpResponse
 10from django.http import HttpResponseServerError
 11
 12from chart.common.util import timedelta_div
 13from chart.common import scid as scid_utils
 14from chart.products.fdf.orbit import NoSuchOrbit
 15from chart.common.texttime import texttime_to_datetime
 16from chart.project import SID
 17from chart.timeconv import convert
 18
 19
 20def index(request):
 21    """Entry page."""
 22    return render(request,
 23                  'timeconv/timeconv.html')
 24
 25
 26def ajax_convert(request):
 27    """Outputs:
 28    YYYY-MM-DD hh:mm:ss
 29    YYYY-DDD hh:mm:ss
 30    matlab
 31    week of year
 32    day of week
 33    matlab
 34    table of surrounding 3 orbits of all scids
 35    ccsds day+ms from ref time
 36    delta from reference time
 37
 38    add button to set as reference time.
 39    """
 40
 41    # First decode the user data
 42    intime = request.GET['time']
 43
 44    logging.info('Timeconv request for {time}'.format(time=intime))
 45
 46    if intime == 'exception':
 47        # used by the unit test test_django.py to verify error handling
 48        return HttpResponseServerError('Test exception requested')
 49
 50    # Now convert the input text into a datetime object
 51    try:
 52        dt = texttime_to_datetime(intime)
 53    except ValueError as e:
 54        return HttpResponse('<p style="color:blue">{message}</p>'.format(message=e))
 55
 56    if dt.year < 1900:
 57        return HttpResponse('<span style="color:red">Please select a date after 1900</span>')
 58
 59    # Extract various output formats from datetime object
 60    date = dt.strftime('%Y-%m-%d')
 61    doy = convert.to_day_of_year(dt)
 62    tod = dt.strftime('%H:%M:%S')
 63    matlab = convert.to_matlab(dt)
 64    week = convert.to_week(dt)
 65    dow = convert.to_day_of_week(dt)
 66    unix = convert.to_unixtime(dt)
 67
 68    if dt > datetime(2000, 1, 1):
 69        ccsds = 'day {days} ms {ms}'.format(days=(dt - datetime(2000, 1, 1)).days,
 70                                            ms=dt.second * 1000 + dt.microsecond / 1000)
 71    else:
 72        ccsds = ''
 73
 74    res = """<table class='table table-striped table-bordered'>
 75<thead>
 76<tr>
 77  <th>Format</th>
 78  <th>Value</th>
 79</tr>
 80</thead>
 81<tbody>
 82<tr>
 83  <td class='key'>Date</td>
 84  <td>{date}</td>
 85</tr>
 86<tr>
 87  <td class='key'>Time of day</td>
 88  <td>{tod}</td>
 89</tr>
 90<tr>
 91  <td class='key'>Day of year</td>
 92  <td>{doy}</td>
 93</tr>
 94<tr>
 95  <td class='key'>ISO8601 Week of year</td>
 96  <td>{week}</td>
 97</tr>
 98<tr>
 99  <td class='key'>Day of week</td>
100  <td>{dow}</td>
101</tr>
102<tr>
103  <td class='key'>MATLAB</td>
104  <td>{matlab}</td>
105</tr>
106<tr>
107  <td class='key'>CCSDS</td>
108  <td>{ccsds}</td>
109</tr>
110<tr>
111  <td class='key'>Unix time</td>
112  <td>{unix}</td>
113</tr>
114""".format(date=date, doy=doy, tod=tod, week=week, dow=dow, matlab=matlab, ccsds=ccsds, unix=unix)
115
116    # now show the orbit numbers for each active satellite for this time
117    for sid in SID.all(operational=True):
118        sat = sid.satellite
119        if sat is None:
120            # gsar?
121            continue
122
123        orb = sid.orbit
124        if orb is None:
125            # satellite without orbit information (msg)
126            continue
127
128        if sat.launch_date is None:
129            # hide satellites with no launch date - probably a SCID used for ground test data only
130            continue
131
132        if sat.launch_date > dt:
133            # hide satellites which have not yet launched
134            continue
135
136        res += '<tr><td class="key">{sid} orbit</td><td>'.format(sid=sid)
137        orbit = orb.find_orbit(dt)
138        if orbit is None:
139            res += '<not found>'
140
141        else:
142            try:
143                start, stop = orb.get_orbit_times(orbit)
144            except NoSuchOrbit:
145                res += 'Not found'
146                continue
147
148            fraction = timedelta_div(dt - start, stop - start)
149            if abs(fraction - 1.0) < 0.01:  # !
150                # this is a bit of a hack... it tried to display correct times at orbit boundaries
151                fraction = 0.0
152                orbit += 1
153                try:
154                    start, stop = orb.get_orbit_times(orbit)
155                except NoSuchOrbit:
156                    res += 'Not found'
157                    continue
158
159            res += 'Number {orbit}<br>Fraction {fraction:.3}<br>' \
160                'Start {start}<br>Stop {stop}'.format(
161                orbit=orbit,
162                fraction=fraction,
163                start=start,
164                stop=stop)
165
166        res += '</td></tr>'
167
168    # ? should be a better way to detect project
169    # if settings.ROOT_URLCONF == 'charteps.urls':
170        # compute OBT time per metop satellite now
171
172    res += '</tbody></table>'
173
174    return HttpResponse(res, content_type='text/html')