Skip to content
Commits on Source (12)
Travel::Status::DE::DeutscheBahn 6.00 - Tue Apr 02 2024
* Add AVV (Aachener Verkehrsverbund), BART (Bay Area Rapid Transit), and IE
(Iarnród Éireann / Irish Rail) backends
* Support backend-specific time zones; add time_zone to service description
* Handle cross-timezone journeys and stops whose time zone differs from
the backend's default time zone. As of this release, all input and output
datetimes refer to the backend's default time zone rather than local
time (Stop and Journey accessors) / whatever (hafas-m and HAFAS
arguments). Use the new tz_offset accessor to determine local time.
This is a breaking change.
* Journey, Stop: Add tz_offset accessor
Travel::Status::DE::DeutscheBahn 5.06 - Thu Mar 28 2024
* Add Travel::Status::DE::HAFAS::Product module to handle line numbers,
......
......@@ -3,7 +3,7 @@ use strict;
use warnings;
use 5.014;
our $VERSION = '5.06';
our $VERSION = '6.00';
use utf8;
use DateTime;
......@@ -51,12 +51,17 @@ GetOptions(
) or show_help(1);
if ($list_services) {
printf( "%-40s %-14s %s\n\n", 'operator', 'abbr. (-s)', 'languages (-l)' );
printf(
"%-40s %-14s %-15s %s\n\n",
'operator', 'abbr. (-s)', 'languages (-l)',
'time zone'
);
for my $service ( Travel::Status::DE::HAFAS::get_services() ) {
printf(
"%-40s %-14s %s\n",
"%-40s %-14s %-15s %s\n",
@{$service}{qw(name shortname)},
join( q{ }, @{ $service->{languages} // [] } )
join( q{ }, @{ $service->{languages} // [] } ),
$service->{time_zone} // q{},
);
}
exit 0;
......@@ -95,7 +100,9 @@ elsif ( $opt{station} =~ m{ ^ [!] (?<query> .*) $ }x ) {
}
if ( $date or $time ) {
my $dt = DateTime->now( time_zone => 'Europe/Berlin' );
my $desc = Travel::Status::DE::HAFAS::get_service($service) // {};
my $dt
= DateTime->now( time_zone => $desc->{time_zone} // 'Europe/Berlin' );
if ($date) {
if ( $date
=~ m{ ^ (?<day> \d{1,2} ) [.] (?<month> \d{1,2} ) [.] (?<year> \d{4})? $ }x
......@@ -355,7 +362,7 @@ if ( $opt{journeyMatch} ) {
say $result->id;
print $result->name;
if ( $result->number ) {
printf( " | Zug %s", $result->number );
printf( " | Nr %s", $result->number );
}
if ( $result->line_no ) {
printf( " | Linie %s", $result->line_no );
......@@ -396,7 +403,7 @@ elsif ( $opt{journey} ) {
printf( "%s → %s", $result->name, $result->route_end );
if ( $result->number ) {
printf( " / Zug %s", $result->number );
printf( " / Nr %s", $result->number );
}
if ( $result->line_no ) {
printf( " / Linie %s", $result->line_no );
......@@ -446,7 +453,9 @@ elsif ( $opt{journey} ) {
}
$prev_prod = 0;
my $now = DateTime->now( time_zone => 'Europe/Berlin' );
my $desc = Travel::Status::DE::HAFAS::get_service($service) // {};
my $now
= DateTime->now( time_zone => $desc->{time_zone} // 'Europe/Berlin' );
my $mark_stop = 0;
for my $i ( reverse 1 .. scalar $result->route ) {
my $stop = ( $result->route )[ $i - 1 ];
......@@ -492,8 +501,28 @@ elsif ( $opt{journey} ) {
$dir_line = '' . $stop->direction;
}
my $tz_line = q{};
if ( $stop->tz_offset and ( $stop->arr or $stop->dep ) ) {
$tz_line = ( $prod_line or $dir_line ) ? q{ · } : q{ };
$tz_line .= 'local ';
if ( $stop->arr ) {
$tz_line
.= $stop->arr->clone->add( minutes => $stop->tz_offset )
->strftime('%H:%M');
}
if ( $stop->arr and $stop->dep ) {
$tz_line .= '';
}
if ( $stop->dep ) {
$tz_line
.= $stop->dep->clone->add( minutes => $stop->tz_offset )
->strftime('%H:%M');
}
$tz_line .= q{ };
}
printf(
"%s%5s %s %5s %-${delay_fmt}s%${occupancy_len}s%-${occupancy_len}s %s%s%s%s%s%s\n",
"%s%5s %s %5s %-${delay_fmt}s%${occupancy_len}s%-${occupancy_len}s %s%s%s%s%s%s%s\n",
$stop == $mark_stop ? $output_bold : q{},
$stop->arr_cancelled ? '--:--'
: ( $stop->arr ? $stop->arr->strftime('%H:%M') : q{} ),
......@@ -507,11 +536,12 @@ elsif ( $opt{journey} ) {
: q{},
$stop->loc->name,
$stop == $mark_stop ? $output_reset : q{},
( $prod_line or $dir_line or $msg_line )
( $tz_line or $prod_line or $dir_line or $msg_line )
? spacer( $stop_len + 1 - length( $stop->loc->name ) )
: q{},
$prod_line,
$dir_line,
$tz_line,
$msg_line,
);
}
......@@ -551,6 +581,7 @@ if ($via) {
my $delay_len = 0;
my $occupancy_len = 0;
my $offset_len = 0;
for my $d (@results) {
if ( $d->delay ) {
$delay_len = max( $delay_len, length( $d->delay ) + 1 );
......@@ -558,6 +589,9 @@ for my $d (@results) {
if ( $d->load and ( $d->load->{FIRST} or $d->load->{SECOND} ) ) {
$occupancy_len = 2;
}
if ( $d->tz_offset ) {
$offset_len = 1;
}
}
my $message_id = 1;
......@@ -586,7 +620,8 @@ for my $d (@results) {
}
my $entry = [
$d->is_cancelled ? '--:--' : $d->datetime->strftime('%H:%M'),
( $d->is_cancelled ? '--:--' : $d->datetime->strftime('%H:%M') )
. ( $d->tz_offset ? q{*} : ( q{ } x $offset_len ) ),
$d->is_cancelled
? q{}
: format_delay( $d->delay, $delay_len ),
......@@ -615,6 +650,11 @@ for my $d (@results) {
display_result(@output);
if ($offset_len) {
printf( "\n* reported for %s; local time differs\n",
$status->get_active_service->{time_zone} // 'Europe/Berlin' );
}
for my $m ( $status->messages ) {
if ( $m->ref_count > 0 and $m->{show} ) {
if ( $m->short ) {
......@@ -643,7 +683,7 @@ B<hafas-m> [B<-s> I<service>] [B<-l> I<language>] B<!>I<query>|I<journeyID>
=head1 VERSION
version 5.06
version 6.00
=head1 DESCRIPTION
......@@ -654,28 +694,27 @@ It has four operating modes that depend on the contents of its argument.
=head2 Arrival/Departure Monitor (I<station>)
Show departures (or arrivals) at I<station>, optionally filtered by date, time
and mode of transport. I<station> may be given as a station name or EVA ID.
EVA IDs tend to be similar to, but not always identical with, UIC station
codes. Output format:
Show departures (or arrivals) at I<station>, optionally filtered by mode of
transport. I<station> may be given as a station name or HAFAS station ID.
=over
=item * scheduled departure (or arrival) time
=item * estimated departure (or arrival) time
=item * delay, if known
=item * trip number or line
=item * trip name, number, or line
=item * direction / destination
=item * platform (B<!> indicates a platform change)
=item * platform, if known (B<!> indicates a platform change)
=item * expected occupancy of first and second class, if known
=back
Occupancy indicators are, from least occupied to fully booked: B<.> B<o>
Departure/arrival times are marked with a C<< * >> if they differ from local
time. Occupancy indicators are, from least occupied to fully booked: B<.> B<o>
B<*> B<!>.
=head2 Location Search (B<?>I<query>|I<lat>B<:>I<lon>)
......@@ -692,7 +731,11 @@ Otherwise, list all journey IDs that match I<query>.
=head2 Trip Details (I<journeyID>)
List intermediate stops of I<journeyID> with arrival/departure time, delay (if
available), occupancy (if available), and stop name.
available), occupancy (if available), and stop name. Also includes
line/journey, operator, and heading information.
Times are reported in the selected HAFAS service's default time zone (typically
Europe/Berlin). If a stop's local time differs, it is also provided.
=head1 OPTIONS
......@@ -722,8 +765,8 @@ Note that requesting an invalid/unsupported language may lead to garbage output.
=item B<--list>
List known HAFAS installations and exit. Use B<-s>|B<--service> to select an
operator from this list for a HAFAS request.
List known HAFAS instances and exit. Use B<-s>|B<--service> to select a
service from this list for a HAFAS request.
=item B<-m>, B<--mot> I<motlist>
......@@ -749,7 +792,8 @@ to DB (Deutsche Bahn). See B<--list> for a list of known services.
=item B<-t>, B<--time> I<hh>:I<mm>
Time to list departures for. Default: now.
Time to list departures for. Must be specified in the selected HAFAS
service's default time zone, see B<--list>. Default: now.
=item B<-v>, B<--via> I<stopname>|I<eva1>,I<eva2>,...
......
......@@ -6,7 +6,7 @@ use 5.014;
use parent 'Travel::Status::DE::HAFAS';
our $VERSION = '5.06';
our $VERSION = '6.00';
sub new {
my ( $class, %opt ) = @_;
......@@ -49,7 +49,7 @@ monitor operated by Deutsche Bahn
=head1 VERSION
version 5.06
version 6.00
=head1 DESCRIPTION
......
......@@ -21,7 +21,7 @@ use Travel::Status::DE::HAFAS::Polyline qw(decode_polyline);
use Travel::Status::DE::HAFAS::Product;
use Travel::Status::DE::HAFAS::StopFinder;
our $VERSION = '5.06';
our $VERSION = '6.00';
# {{{ Endpoint Definition
......@@ -63,6 +63,7 @@ my %hafas_instance = (
stopfinder => 'https://planner.bart.gov/bin/ajax-getstop.exe',
mgate => 'https://planner.bart.gov/bin/mgate.exe',
name => 'Bay Area Rapid Transit',
time_zone => 'America/Los_Angeles',
productbits => [
[ _ => undef ],
[ _ => undef ],
......@@ -118,6 +119,7 @@ my %hafas_instance = (
'https://journeyplanner.irishrail.ie/bin/ajax-getstop.exe',
mgate => 'https://journeyplanner.irishrail.ie/bin/mgate.exe',
name => 'Iarnród Éireann',
time_zone => 'Europe/Dublin',
productbits => [
[ _ => undef ],
[ ic => 'national trains' ],
......@@ -215,6 +217,7 @@ my %hafas_instance = (
mgate => 'https://fahrplan.oebb.at/bin/mgate.exe',
stopfinder => 'https://fahrplan.oebb.at/bin/ajax-getstop.exe',
name => 'Österreichische Bundesbahnen',
time_zone => 'Europe/Vienna',
productbits => [
[ ice_rj => 'long distance trains' ],
[ sev => 'rail replacement service' ],
......@@ -328,7 +331,8 @@ sub new {
confess("The service '$service' is not supported");
}
my $now = DateTime->now( time_zone => 'Europe/Berlin' );
my $now = DateTime->now( time_zone => $hafas_instance{$service}{time_zone}
// 'Europe/Berlin' );
my $self = {
active_service => $service,
arrivals => $conf{arrivals},
......@@ -341,6 +345,7 @@ sub new {
station => $conf{station},
ua => $ua,
now => $now,
tz_offset => $now->offset / 60,
};
bless( $self, $obj );
......@@ -482,7 +487,7 @@ sub new {
$self->{strptime_obj} //= DateTime::Format::Strptime->new(
pattern => '%Y%m%dT%H%M%S',
time_zone => 'Europe/Berlin',
time_zone => $hafas_instance{$service}{time_zone} // 'Europe/Berlin',
);
my $json = $self->{json} = JSON->new->utf8;
......@@ -1135,7 +1140,7 @@ monitors
=head1 VERSION
version 5.06
version 6.00
=head1 DESCRIPTION
......@@ -1370,17 +1375,42 @@ arguments. Otherwise, the caller must specify B<promise> and B<user_agent>
=item $status->get_active_service
Returns a hashref describing the active service when a service is active and
nothing otherwise. The hashref contains the keys B<url> (URL to the station
board service), B<stopfinder> (URL to the stopfinder service, if supported),
B<name>, and B<productbits> (arrayref describing the supported modes of
transport, may contain duplicates).
nothing otherwise. The hashref contains the following keys.
=over
=item B<name> => I<string>
service name, e.g. Bay Area Rapid Transit or Deutsche Bahn.
=item B<mgate> => I<string>
HAFAS backend URL
=item B<languages> => I<arrayref>
Languages supported by the backend; see the constructor's B<language> argument.
=item B<productbits> => I<arrayref>
MOT bits supported by the backend. I<arrayref> contains either strings
(one string per mode of transit) or arrayrefs (one string pair per mode of
transit, with the first entry referring to the MOT identifier and the second
one containing a slightly longer description of it).
=item B<time_zone> => I<string> (optional)
The time zone this service reports arrival/departure times in. If this key is
not present, it is safe to assume that it uses Europe/Berlin.
=back
=item Travel::Status::DE::HAFAS::get_services()
Returns an array containing all supported HAFAS services. Each element is a
hashref and contains all keys mentioned in B<get_active_service>.
It also contains a B<shortname> key, which is the service name used by
the constructor's B<service> parameter.
the constructor's B<service> parameter, e.g. BART or DB.
=item Travel::Status::DE::HAFAS::get_service(I<$service>)
......
......@@ -11,10 +11,10 @@ use DateTime::Format::Strptime;
use List::Util qw(any);
use Travel::Status::DE::HAFAS::Stop;
our $VERSION = '5.06';
our $VERSION = '6.00';
Travel::Status::DE::HAFAS::Journey->mk_ro_accessors(
qw(datetime sched_datetime rt_datetime
qw(datetime sched_datetime rt_datetime tz_offset
is_additional is_cancelled is_partially_cancelled
station station_eva platform sched_platform rt_platform operator
product
......@@ -94,7 +94,8 @@ sub new {
}
$datetime_ref = DateTime::Format::Strptime->new(
pattern => $parse_fmt,
time_zone => 'Europe/Berlin'
time_zone => $hafas->get_active_service->{time_zone}
// 'Europe/Berlin'
)->parse_datetime($date_ref);
}
......@@ -173,27 +174,33 @@ sub new {
// $journey->{stbStop}{dPltfR}{txt};
$ref->{platform} = $ref->{rt_platform} // $ref->{sched_platform};
my $time_s
= $journey->{stbStop}{ $hafas->{arrivals} ? 'aTimeS' : 'dTimeS' };
my $time_r
= $journey->{stbStop}{ $hafas->{arrivals} ? 'aTimeR' : 'dTimeR' };
for my $timestr ( $time_s, $time_r ) {
if ( not defined $timestr ) {
next;
}
$timestr = Travel::Status::DE::HAFAS::Stop::handle_day_change(
input => $timestr,
date => $date,
strp_obj => $hafas->{strptime_obj},
ref => $datetime_ref,
);
}
my $datetime_s = Travel::Status::DE::HAFAS::Stop::handle_day_change(
$ref,
input =>
$journey->{stbStop}{ $hafas->{arrivals} ? 'aTimeS' : 'dTimeS' },
offset => $journey->{stbStop}{
$hafas->{arrivals}
? 'aTZOffset'
: 'dTZOffset'
},
date => $date,
strp_obj => $hafas->{strptime_obj},
ref => $datetime_ref,
);
my $datetime_s = $time_s;
my $datetime_r = $time_r;
my $datetime_r = Travel::Status::DE::HAFAS::Stop::handle_day_change(
$ref,
input =>
$journey->{stbStop}{ $hafas->{arrivals} ? 'aTimeR' : 'dTimeR' },
offset => $journey->{stbStop}{
$hafas->{arrivals}
? 'aTZOffset'
: 'dTZOffset'
},
date => $date,
strp_obj => $hafas->{strptime_obj},
ref => $datetime_ref,
);
my $delay
= $datetime_r
......@@ -395,7 +402,7 @@ journey received by Travel::Status::DE::HAFAS
=head1 VERSION
version 5.06
version 6.00
=head1 DESCRIPTION
......@@ -404,7 +411,9 @@ a station-specific arrival/departure obtained by a stationboard query, or a
train journey that does not belong to a specific station.
stationboard-specific accessors are annotated with "(station only)" and return
undef for non-station journeys.
undef for non-station journeys. All date and time entries refer to the
backend time zone (Europe/Berlin in most cases) and do not take local time
into account; see B<tz_offset> for the latter.
=head1 METHODS
......@@ -472,6 +481,13 @@ DateTime object indicating the arrival/departure date and time.
Real-time data if available, schedule data otherwise.
undef if neither is available.
=item $journey->tz_offset
Offset between backend time zone (default: Europe/Berlin) and this journey's
time zone in minutes, if any. For instance, if the backend uses UTC+2 (CEST)
and the journey uses UTC+1 (IST), tz_offset is -60. Returns undef if both use
the same time zone (or rather, the same UTC offset).
=item $journey->delay (station only)
Delay in minutes, or undef if it is unknown.
......
......@@ -6,7 +6,7 @@ use 5.014;
use parent 'Class::Accessor';
our $VERSION = '5.06';
our $VERSION = '6.00';
Travel::Status::DE::HAFAS::Location->mk_ro_accessors(
qw(lid type name eva state lat lon distance_m weight));
......@@ -57,7 +57,7 @@ Travel::Status::DE::HAFAS::Location - A single public transit location
=head1 VERSION
version 5.06
version 6.00
=head1 DESCRIPTION
......
......@@ -6,7 +6,7 @@ use 5.014;
use parent 'Class::Accessor';
our $VERSION = '5.06';
our $VERSION = '6.00';
Travel::Status::DE::HAFAS::Message->mk_ro_accessors(
qw(short type text code prio is_him ref_count));
......@@ -69,7 +69,7 @@ Travel::Status::DE::HAFAS::Message - An arrival/departure-related message.
=head1 VERSION
version 5.06
version 6.00
=head1 DESCRIPTION
......
......@@ -16,7 +16,7 @@ use 5.014;
use parent 'Exporter';
our @EXPORT_OK = qw(decode_polyline);
our $VERSION = '5.06';
our $VERSION = '6.00';
# Translated this php script
# <http://unitstep.net/blog/2008/08/02/decoding-google-maps-encoded-polylines-using-php/>
......
......@@ -8,7 +8,7 @@ use 5.014;
use parent 'Class::Accessor';
our $VERSION = '5.06';
our $VERSION = '6.00';
Travel::Status::DE::HAFAS::Product->mk_ro_accessors(
qw(class line_id line_no name number type type_long operator));
......@@ -105,7 +105,7 @@ associated with a journey.
=head1 VERSION
version 5.06
version 6.00
=head1 DESCRIPTION
......
......@@ -8,7 +8,7 @@ use 5.014;
use parent 'Class::Accessor';
our $VERSION = '5.06';
our $VERSION = '6.00';
Travel::Status::DE::HAFAS::Stop->mk_ro_accessors(
qw(loc
......@@ -16,7 +16,7 @@ Travel::Status::DE::HAFAS::Stop->mk_ro_accessors(
rt_dep sched_dep dep dep_delay dep_cancelled prod_dep
delay direction
rt_platform sched_platform platform is_changed_platform
is_additional
is_additional tz_offset
load
)
);
......@@ -34,11 +34,6 @@ sub new {
my $hafas = $opt{hafas};
my $strp_obj = $opt{hafas}{strptime_obj};
my $sched_arr = $stop->{aTimeS};
my $rt_arr = $stop->{aTimeR};
my $sched_dep = $stop->{dTimeS};
my $rt_dep = $stop->{dTimeR};
my $prod_arr
= defined $stop->{aProdX} ? $prodL->[ $stop->{aProdX} ] : undef;
my $prod_dep
......@@ -50,33 +45,76 @@ sub new {
my $rt_platform = $stop->{aPlatfR} // $stop->{dPlatfR};
my $changed_platform = $stop->{aPlatfCh} // $stop->{dPlatfCh};
for my $timestr ( $sched_arr, $rt_arr, $sched_dep, $rt_dep ) {
if ( not defined $timestr ) {
next;
}
my $arr_cancelled = $stop->{aCncl};
my $dep_cancelled = $stop->{dCncl};
my $is_additional = $stop->{isAdd};
$timestr = handle_day_change(
input => $timestr,
date => $date,
strp_obj => $strp_obj,
ref => $datetime_ref
);
my $ref = {
loc => $opt{loc},
direction => $stop->{dDirTxt},
sched_platform => $sched_platform,
rt_platform => $rt_platform,
is_changed_platform => $changed_platform,
platform => $rt_platform // $sched_platform,
arr_cancelled => $arr_cancelled,
dep_cancelled => $dep_cancelled,
is_additional => $is_additional,
prod_arr => $prod_arr,
prod_dep => $prod_dep,
};
}
bless( $ref, $obj );
my $arr_delay
my $sched_arr = $ref->handle_day_change(
input => $stop->{aTimeS},
offset => $stop->{aTZOffset},
date => $date,
strp_obj => $strp_obj,
ref => $datetime_ref
);
my $rt_arr = $ref->handle_day_change(
input => $stop->{aTimeR},
offset => $stop->{aTZOffset},
date => $date,
strp_obj => $strp_obj,
ref => $datetime_ref
);
my $sched_dep = $ref->handle_day_change(
input => $stop->{dTimeS},
offset => $stop->{dTZOffset},
date => $date,
strp_obj => $strp_obj,
ref => $datetime_ref
);
my $rt_dep = $ref->handle_day_change(
input => $stop->{dTimeR},
offset => $stop->{dTZOffset},
date => $date,
strp_obj => $strp_obj,
ref => $datetime_ref
);
$ref->{arr_delay}
= ( $sched_arr and $rt_arr )
? ( $rt_arr->epoch - $sched_arr->epoch ) / 60
: undef;
my $dep_delay
$ref->{dep_delay}
= ( $sched_dep and $rt_dep )
? ( $rt_dep->epoch - $sched_dep->epoch ) / 60
: undef;
my $arr_cancelled = $stop->{aCncl};
my $dep_cancelled = $stop->{dCncl};
my $is_additional = $stop->{isAdd};
$ref->{delay} = $ref->{dep_delay} // $ref->{arr_delay};
$ref->{sched_arr} = $sched_arr;
$ref->{sched_dep} = $sched_dep;
$ref->{rt_arr} = $rt_arr;
$ref->{rt_dep} = $rt_dep;
$ref->{arr} = $rt_arr // $sched_arr;
$ref->{dep} = $rt_dep // $sched_dep;
my @messages;
for my $msg ( @{ $stop->{msgL} // [] } ) {
......@@ -92,49 +130,29 @@ sub new {
say "Unknown message type $msg->{type}";
}
}
$ref->{messages} = \@messages;
my $tco = {};
$ref->{load} = {};
for my $tco_id ( @{ $stop->{dTrnCmpSX}{tcocX} // [] } ) {
my $tco_kv = $common->{tcocL}[$tco_id];
$tco->{ $tco_kv->{c} } = $tco_kv->{r};
$ref->{load}{ $tco_kv->{c} } = $tco_kv->{r};
}
my $ref = {
loc => $opt{loc},
sched_arr => $sched_arr,
rt_arr => $rt_arr,
arr => $rt_arr // $sched_arr,
arr_delay => $arr_delay,
arr_cancelled => $arr_cancelled,
prod_arr => $prod_arr,
sched_dep => $sched_dep,
rt_dep => $rt_dep,
dep => $rt_dep // $sched_dep,
dep_delay => $dep_delay,
dep_cancelled => $dep_cancelled,
prod_dep => $prod_dep,
delay => $dep_delay // $arr_delay,
direction => $stop->{dDirTxt},
sched_platform => $sched_platform,
rt_platform => $rt_platform,
is_changed_platform => $changed_platform,
platform => $rt_platform // $sched_platform,
is_additional => $is_additional,
load => $tco,
messages => \@messages,
};
bless( $ref, $obj );
return $ref;
}
# }}}
sub handle_day_change {
my (%opt) = @_;
my ( $self, %opt ) = @_;
my $date = $opt{date};
my $timestr = $opt{input};
my $offset = $opt{offset};
if ( not defined $timestr ) {
return;
}
if ( length($timestr) == 8 ) {
# arrival time includes a day offset
......@@ -146,6 +164,12 @@ sub handle_day_change {
else {
$timestr = $opt{strp_obj}->parse_datetime("${date}T${timestr}");
}
if ( defined $offset and $offset != $timestr->offset / 60 ) {
$self->{tz_offset} = $offset - $timestr->offset / 60;
$timestr->subtract( minutes => $self->{tz_offset} );
}
return $timestr;
}
......@@ -194,7 +218,7 @@ Travel::Status::DE::HAFAS::Stop - Information about a HAFAS stop.
=head1 VERSION
version 5.06
version 6.00
=head1 DESCRIPTION
......@@ -203,6 +227,10 @@ Travel::Status::DE::HAFAS::Journey(3pm)'s stop at a given
Travel::Status::DE::HAFAS::Location(3pm) with arrival/departure time,
platform, etc.
All date and time entries refer to the backend time zone (Europe/Berlin in most
cases) and do not take local time into account; see B<tz_offset> for the
latter.
=head1 METHODS
=head2 ACCESSORS
......@@ -254,6 +282,13 @@ Departure delay in minutes.
Departure is cancelled.
=item $stop->tz_offset
Offset between backend time zone (default: Europe/Berlin) and this stop's time
zone in minutes, if any. For instance, if the backend uses UTC+2 (CEST) and the
stop uses UTC+1 (IST), tz_offset is -60. Returns undef if both use the same
time zone (or rather, the same UTC offset).
=item $stop->delay
Departure or arrival delay in minutes.
......
......@@ -10,7 +10,7 @@ use Encode qw(decode);
use JSON;
use LWP::UserAgent;
our $VERSION = '5.06';
our $VERSION = '6.00';
# {{{ Constructors
......@@ -180,7 +180,7 @@ finder services
=head1 VERSION
version 5.06
version 6.00
=head1 DESCRIPTION
......
......@@ -2,7 +2,10 @@
export PERL5LIB=lib
checks="DB Berlin Jannowitzbrücke
checks="AVV Ponttor, AC
BART San Francisco International Airport, San Mateo
DB Berlin Jannowitzbrücke
IE Dublin
NAHSH Flensburg
NASA Wernigerode Hbf
NVV Kassel Hauptbahnhof
......