summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBirte Kristina Friesel <derf@finalrewind.org>2025-07-05 18:40:23 +0200
committerBirte Kristina Friesel <derf@finalrewind.org>2025-07-05 18:40:23 +0200
commite5edf5b81567e1f79db64499c2ac3554d7508d81 (patch)
treed445994d53e0600832ad1f438d2dcb607f8ab77a
parent45771233e9db681a632aa4408cb17e379c55ff6b (diff)
parent5a65ee90d146f19999837853e8311e5b03e31af8 (diff)
Merge branch 'date-inputs' of github.com:deingithub/travelynx
-rwxr-xr-xlib/Travelynx/Controller/Traveling.pm48
-rw-r--r--sass/src/dark/index.scss2
-rw-r--r--t/11-journey-stats.t20
-rw-r--r--t/12-journey-edit.t40
-rw-r--r--templates/add_intransit.html.ep12
-rw-r--r--templates/add_journey.html.ep18
-rw-r--r--templates/edit_journey.html.ep8
-rw-r--r--templates/history_by_month.html.ep2
-rw-r--r--templates/history_by_year.html.ep4
-rw-r--r--templates/history_map.html.ep8
10 files changed, 89 insertions, 73 deletions
diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm
index fd2abb1..74bb5c6 100755
--- a/lib/Travelynx/Controller/Traveling.pm
+++ b/lib/Travelynx/Controller/Traveling.pm
@@ -1745,13 +1745,12 @@ sub map_history {
my $with_polyline = $route_type eq 'beeline' ? 0 : 1;
my $parser = DateTime::Format::Strptime->new(
- pattern => '%d.%m.%Y',
+ pattern => '%F',
locale => 'de_DE',
time_zone => 'Europe/Berlin'
);
- if ( $filter_from
- and $filter_from =~ m{ ^ (\d+) [.] (\d+) [.] (\d+) $ }x )
+ if ( $filter_from )
{
$filter_from = $parser->parse_datetime($filter_from);
}
@@ -1759,8 +1758,7 @@ sub map_history {
$filter_from = undef;
}
- if ( $filter_until
- and $filter_until =~ m{ ^ (\d+) [.] (\d+) [.] (\d+) $ }x )
+ if ( $filter_until )
{
$filter_until = $parser->parse_datetime($filter_until)->set(
hour => 23,
@@ -2383,7 +2381,7 @@ sub edit_journey {
if ( $self->param('action') and $self->param('action') eq 'save' ) {
my $parser = DateTime::Format::Strptime->new(
- pattern => '%d.%m.%Y %H:%M',
+ pattern => '%FT%H:%M',
locale => 'de_DE',
time_zone => 'Europe/Berlin'
);
@@ -2486,7 +2484,7 @@ sub edit_journey {
for my $key (qw(sched_departure rt_departure sched_arrival rt_arrival)) {
if ( $journey->{$key} and $journey->{$key}->epoch ) {
$self->param(
- $key => $journey->{$key}->strftime('%d.%m.%Y %H:%M') );
+ $key => $journey->{$key}->strftime('%FT%H:%M') );
}
}
@@ -2518,7 +2516,7 @@ sub add_journey_form {
if ( $self->param('action') and $self->param('action') eq 'save' ) {
my $parser = DateTime::Format::Strptime->new(
- pattern => '%d.%m.%Y %H:%M',
+ pattern => '%FT%H:%M',
locale => 'de_DE',
time_zone => 'Europe/Berlin'
);
@@ -2619,7 +2617,12 @@ sub add_intransit_form {
if ( $self->param('action') and $self->param('action') eq 'save' ) {
my $parser = DateTime::Format::Strptime->new(
- pattern => '%d.%m.%Y %H:%M',
+ pattern => '%FT%H:%M',
+ locale => 'de_DE',
+ time_zone => 'Europe/Berlin'
+ );
+ my $time_parser = DateTime::Format::Strptime->new(
+ pattern => '%H:%M',
locale => 'de_DE',
time_zone => 'Europe/Berlin'
);
@@ -2710,7 +2713,7 @@ sub add_intransit_form {
if ( $trip{route} ) {
my @unknown_stations;
- my $prev_epoch;
+ my $prev_ts = $trip{sched_departure};
for my $station ( @{ $trip{route} } ) {
my $ts;
my %station_data;
@@ -2719,11 +2722,30 @@ sub add_intransit_form {
)
{
$station = $+{stop};
- $ts = $parser->parse_datetime( $+{timestamp} );
- if ( $ts and $ts->epoch > $prev_epoch ) {
+ # attempt to parse "07:08" short timestamp first
+ $ts = $time_parser->parse_datetime( $+{timestamp} );
+ if ( $ts ) {
+ # fill in last stop's (or at the first stop, our departure's)
+ # date to complete the datetime
+ $ts = $ts->set(
+ year => $prev_ts->year,
+ month => $prev_ts->month,
+ day => $prev_ts->day
+ );
+ # if we go back in time with this, assume we went
+ # over midnight and add a day, e.g. in case of a stop
+ # at 23:00 followed by one at 01:30
+ if ($ts < $prev_ts) {
+ $ts = $ts->add( days => 1 );
+ }
+ } else {
+ # do a full datetime parse
+ $ts = $parser->parse_datetime( $+{timestamp} );
+ }
+ if ( $ts and $ts >= $prev_ts ) {
$station_data{sched_arr} = $ts->epoch;
$station_data{sched_dep} = $ts->epoch;
- $prev_epoch = $ts->epoch;
+ $prev_ts = $ts;
}
else {
$self->render(
diff --git a/sass/src/dark/index.scss b/sass/src/dark/index.scss
index 28c615b..310a8a4 100644
--- a/sass/src/dark/index.scss
+++ b/sass/src/dark/index.scss
@@ -18,6 +18,8 @@ html {
input[type=email],
input[type=text],
input[type=password],
+input[type=date],
+input[type=datetime-local],
textarea {
color: $off-black;
}
diff --git a/t/11-journey-stats.t b/t/11-journey-stats.t
index 4623402..3fc8724 100644
--- a/t/11-journey-stats.t
+++ b/t/11-journey-stats.t
@@ -82,11 +82,11 @@ $t->post_ok(
action => 'save',
train => 'RE 42 11238',
dep_station => 'EMSTP',
- sched_departure => '16.10.2018 17:36',
- rt_departure => '16.10.2018 17:36',
+ sched_departure => '2018-10-16T17:36',
+ rt_departure => '2018-10-16T17:36',
arr_station => 'EG',
- sched_arrival => '16.10.2018 18:34',
- rt_arrival => '16.10.2018 18:34',
+ sched_arrival => '2018-10-16T18:34',
+ rt_arrival => '2018-10-16T18:34',
comment => 'Passierschein A38',
}
);
@@ -123,11 +123,11 @@ $t->post_ok(
action => 'save',
train => 'RE 42 11238',
dep_station => 'EMSTP',
- sched_departure => '16.11.2018 17:36',
- rt_departure => '16.11.2018 17:45',
+ sched_departure => '2018-11-16T17:36',
+ rt_departure => '2018-11-16T17:45',
arr_station => 'EG',
- sched_arrival => '16.11.2018 18:34',
- rt_arrival => '16.11.2018 19:00',
+ sched_arrival => '2018-11-16T18:34',
+ rt_arrival => '2018-11-16T19:00',
}
);
$t->status_is(302)->header_is( location => '/journey/2' );
@@ -153,10 +153,10 @@ $t->post_ok(
action => 'save',
train => 'ICE 1',
dep_station => 'EE',
- sched_departure => '17.11.2018 15:42',
+ sched_departure => '2018-11-17T15:42',
rt_departure => '',
arr_station => 'BL',
- sched_arrival => '17.11.2018 19:42',
+ sched_arrival => '2018-11-17T19:42',
rt_arrival => '',
}
);
diff --git a/t/12-journey-edit.t b/t/12-journey-edit.t
index 5854d62..7a2d127 100644
--- a/t/12-journey-edit.t
+++ b/t/12-journey-edit.t
@@ -145,14 +145,10 @@ $t->post_ok(
}
);
-$t->status_is(200)
- ->content_like(qr{M.nster\(Westf\)Hbf})
- ->content_like(qr{Gelsenkirchen Hbf})
- ->content_like(qr{RE 11238})
- ->content_like(qr{Linie 42})
- ->content_like(qr{16.10.2018 ..:36})
- ->content_like(qr{16.10.2018 ..:34})
- ->content_like(qr{Huhu});
+$t->status_is(200)->content_like(qr{M.nster\(Westf\)Hbf})
+ ->content_like(qr{Gelsenkirchen Hbf})->content_like(qr{RE 11238})
+ ->content_like(qr{Linie 42})->content_like(qr{2018-10-16T..:36})
+ ->content_like(qr{2018-10-16T..:34})->content_like(qr{Huhu});
$csrf_token = $t->tx->res->dom->at('input[name=csrf_token]')->attr('value');
@@ -163,10 +159,10 @@ $t->post_ok(
csrf_token => $csrf_token,
from_name => 'Münster(Westf)Hbf',
to_name => 'Gelsenkirchen Hbf',
- sched_departure => '16.10.2018 17:36',
- rt_departure => '16.10.2018 17:36',
- sched_arrival => '16.10.2018 18:34',
- rt_arrival => '16.10.2018 18:34',
+ sched_departure => '2018-10-16T17:36',
+ rt_departure => '2018-10-16T17:36',
+ sched_arrival => '2018-10-16T18:34',
+ rt_arrival => '2018-10-16T18:34',
}
);
@@ -193,14 +189,10 @@ $t->post_ok(
}
);
-$t->status_is(200)
- ->content_like(qr{M.nster\(Westf\)Hbf})
- ->content_like(qr{Gelsenkirchen Hbf})
- ->content_like(qr{RE 11238})
- ->content_like(qr{Linie 42})
- ->content_like(qr{16.10.2018 ..:36})
- ->content_like(qr{16.10.2018 ..:34})
- ->content_like(qr{Huhu});
+$t->status_is(200)->content_like(qr{M.nster\(Westf\)Hbf})
+ ->content_like(qr{Gelsenkirchen Hbf})->content_like(qr{RE 11238})
+ ->content_like(qr{Linie 42})->content_like(qr{2018-10-16T..:36})
+ ->content_like(qr{2018-10-16T..:34})->content_like(qr{Huhu});
$csrf_token = $t->tx->res->dom->at('input[name=csrf_token]')->attr('value');
@@ -211,10 +203,10 @@ $t->post_ok(
csrf_token => $csrf_token,
from_name => 'Münster(Westf)Hbf',
to_name => 'Gelsenkirchen Hbf',
- sched_departure => '16.10.2018 17:36',
- rt_departure => '16.10.2018 17:42',
- sched_arrival => '16.10.2018 18:34',
- rt_arrival => '16.10.2018 18:33',
+ sched_departure => '2018-10-16T17:36',
+ rt_departure => '2018-10-16T17:42',
+ sched_arrival => '2018-10-16T18:34',
+ rt_arrival => '2018-10-16T18:33',
}
);
diff --git a/templates/add_intransit.html.ep b/templates/add_intransit.html.ep
index 9d711c9..a044917 100644
--- a/templates/add_intransit.html.ep
+++ b/templates/add_intransit.html.ep
@@ -21,7 +21,7 @@
<li>Eingabe der Fahrt als „Typ Linie Nummer“ oder „Typ Nummer“, z.B.
„ICE 100“, „S 1 31133“ oder „ABR RE11 26720“</li>
<li>Wenn Nummer nicht bekannt oder vorhanden: einen beliebigen Integer eintragen, z.B. „S 5X 0“ oder „U 11 0“</li>
- <li>Zeitangaben im Format DD.MM.YYYY HH:MM</li>
+ <li>Zeitangaben im Format YYYY-MM-DDTHH:MM. Bei den Zwischenhalten kann auch nur HH:MM angegeben werden</li>
<li>Das ausgewählte Backend bestimmt die verfügbaren Halte für Start, Ziel und Route. Siehe auch <a href="/static/stops.csv">stops.csv</a></li>
</ul>
</div>
@@ -50,8 +50,8 @@
<label for="dep_station">Start (Name oder ID)</label>
</div>
<div class="input-field col s12">
- %= text_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
- <label for="sched_departure">Geplante Abfahrt</label>
+ %= datetime_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef
+ <label for="sched_departure" class="active">Geplante Abfahrt</label>
</div>
</div>
<div class="row">
@@ -60,8 +60,8 @@
<label for="arr_station">Ziel (Name oder ID)</label>
</div>
<div class="input-field col s12">
- %= text_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
- <label for="sched_arrival">Geplante Ankunft</label>
+ %= datetime_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef
+ <label for="sched_arrival" class="active">Geplante Ankunft</label>
</div>
</div>
<div class="row">
@@ -69,7 +69,7 @@
%= text_area 'route', id => 'route', class => 'materialize-textarea'
<label for="route">Halte (optional)</label><br/>
Eine Station pro Zeile, wahlweise Unterwegshalte oder komplette Route<br/>
- Format: <i>Name</i> oder <i>Name</i> @ <i>Zeitpunkt</i> (inkl. Datum, siehe oben)
+ Format: <i>Name</i> oder <i>Name</i> @ <i>Zeitpunkt</i> (Format siehe oben, ein ggf. ausgelassenes Datum wird ergänzt)
</div>
</div>
<div class="row">
diff --git a/templates/add_journey.html.ep b/templates/add_journey.html.ep
index cade37e..94f9270 100644
--- a/templates/add_journey.html.ep
+++ b/templates/add_journey.html.ep
@@ -33,7 +33,7 @@
<li>Eingabe der Fahrt als „Typ Linie Nummer“ oder „Typ Nummer“, z.B.
„ICE 100“, „S 1 31133“ oder „ABR RE11 26720“</li>
<li>Wenn Nummer nicht bekannt oder vorhanden: einen beliebigen Integer eintragen, z.B. „S 5X 0“ oder „U 11 0“</li>
- <li>Zeitangaben im Format DD.MM.YYYY HH:MM</li>
+ <li>Zeitangaben im Format YYYY-MM-DDTHH:MM</li>
<li>Das ausgewählte Backend bestimmt die verfügbaren Halte für Start, Ziel und Route. Siehe auch <a href="/static/stops.csv">stops.csv</a></li>
</ul>
</div>
@@ -69,12 +69,12 @@
<label for="dep_station">Start (Name oder ID)</label>
</div>
<div class="input-field col s12">
- %= text_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
- <label for="sched_departure">Geplante Abfahrt</label>
+ %= datetime_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef
+ <label for="sched_departure" class="active">Geplante Abfahrt</label>
</div>
<div class="input-field col s12">
- %= text_field 'rt_departure', id => 'rt_departure', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
- <label for="rt_departure">Tatsächliche Abfahrt (wenn leer: pünktlich)</label>
+ %= datetime_field 'rt_departure', id => 'rt_departure', class => 'validate'
+ <label for="rt_departure" class="active">Tatsächliche Abfahrt (wenn leer: pünktlich)</label>
</div>
</div>
<div class="row">
@@ -83,12 +83,12 @@
<label for="arr_station">Ziel (Name oder ID)</label>
</div>
<div class="input-field col s12">
- %= text_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
- <label for="sched_arrival">Geplante Ankunft</label>
+ %= datetime_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef
+ <label for="sched_arrival" class="active">Geplante Ankunft</label>
</div>
<div class="input-field col s12">
- %= text_field 'rt_arrival', id => 'rt_arrival', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
- <label for="rt_arrival">Tatsächliche Ankunft (wenn leer: pünktlich)</label>
+ %= datetime_field 'rt_arrival', id => 'rt_arrival', class => 'validate'
+ <label for="rt_arrival" class="active">Tatsächliche Ankunft (wenn leer: pünktlich)</label>
</div>
</div>
<div class="row">
diff --git a/templates/edit_journey.html.ep b/templates/edit_journey.html.ep
index cb867e5..6316731 100644
--- a/templates/edit_journey.html.ep
+++ b/templates/edit_journey.html.ep
@@ -69,13 +69,13 @@
<tr>
<th scope="row">Geplante Abfahrt</th>
<td class="input-field">
- %= text_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
+ %= datetime_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef
</td>
</tr>
<tr>
<th scope="row">Tatsächliche Abfahrt</th>
<td class="input-field">
- %= text_field 'rt_departure', id => 'real_departure', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
+ %= datetime_field 'rt_departure', id => 'real_departure', class => 'validate'
</td>
</tr>
<tr>
@@ -87,13 +87,13 @@
<tr>
<th scope="row">Geplante Ankunft</th>
<td class="input-field">
- %= text_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
+ %= datetime_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef
</td>
</tr>
<tr>
<th scope="row">Tatsächliche Ankunft</th>
<td class="input-field">
- %= text_field 'rt_arrival', id => 'real_arrival', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
+ %= datetime_field 'rt_arrival', id => 'real_arrival', class => 'validate'
</td>
</tr>
<tr>
diff --git a/templates/history_by_month.html.ep b/templates/history_by_month.html.ep
index c3b1004..dec4c8b 100644
--- a/templates/history_by_month.html.ep
+++ b/templates/history_by_month.html.ep
@@ -6,7 +6,7 @@
<div class="row">
<div class="col s12 m12 l12 center-align">
- <a href="/history/map?filter_from=<%= $filter_from->strftime('%d.%m.%Y') %>&amp;filter_to=<%= $filter_to->strftime('%d.%m.%Y') %>" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a>
+ <a href="/history/map?filter_from=<%= $filter_from->strftime('%F') %>&amp;filter_to=<%= $filter_to->strftime('%F') %>" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a>
</div>
</div>
diff --git a/templates/history_by_year.html.ep b/templates/history_by_year.html.ep
index 6aa0c2d..1557b77 100644
--- a/templates/history_by_year.html.ep
+++ b/templates/history_by_year.html.ep
@@ -7,7 +7,7 @@
<div class="row">
% if (stash('have_review')) {
<div class="col s12 m12 l5 center-align">
- <a href="/history/map?filter_from=1.1.<%= $year %>&amp;filter_to=31.12.<%= $year %>" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a>
+ <a href="/history/map?filter_from=<%= $year %>-01-01&amp;filter_to=<%= $year %>-12-31" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a>
</div>
<div class="col s12 m12 l2">&nbsp;</div>
<div class="col s12 m12 l5 center-align">
@@ -16,7 +16,7 @@
% }
% else {
<div class="col s12 m12 l12 center-align">
- <a href="/history/map?filter_from=1.1.<%= $year %>&amp;filter_to=31.12.<%= $year %>" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a>
+ <a href="/history/map?filter_from=<%= $year %>-01-01&amp;filter_to=<%= $year %>-12-31" class="waves-effect waves-light btn"><i class="material-icons left" aria-hidden="true">map</i> Karte</a>
</div>
% }
</div>
diff --git a/templates/history_map.html.ep b/templates/history_map.html.ep
index c2ff9ed..6620cb2 100644
--- a/templates/history_map.html.ep
+++ b/templates/history_map.html.ep
@@ -88,14 +88,14 @@
</p>
<div class="row">
<div class="input-field col s12">
- %= text_field 'filter_from', id => 'filter_from', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9]( +[0-9][0-9]:[0-9][0-9])?'
- <label for="filter_from">Abfahrt ab (DD.MM.YYYY)</label>
+ %= date_field 'filter_from', id => 'filter_from', class => 'validate'
+ <label for="filter_from" class="active">Abfahrt ab</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
- %= text_field 'filter_to', id => 'filter_to', class => 'validate', pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9]( +[0-9][0-9]:[0-9][0-9])?'
- <label for="filter_to">Abfahrt bis (DD.MM.YYYY)</label>
+ %= date_field 'filter_to', id => 'filter_to', class => 'validate'
+ <label for="filter_to" class="active">Abfahrt bis</label>
</div>
</div>
<div class="row">