Add Time Only Local and UTC Helpers - #49
Conversation
| def to_local_from_anchor(time, trip_date, timezone: "America/Toronto") | ||
| raise MissingAnchorDateError if trip_date.nil? | ||
| return nil if time.blank? | ||
| hour = time.split(":").first.to_i |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| to_local_from_anchor(time, trip_date, timezone: timezone)&.utc | ||
| end | ||
|
|
||
| def to_local_from_anchor(time, trip_date, timezone: "America/Toronto") |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| date.in_time_zone(timezone) | ||
| end | ||
|
|
||
| def to_utc_from_anchor(time, trip_date, timezone: "America/Toronto") |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| @@ -1,3 +1,3 @@ | |||
| module GoTransit | |||
| VERSION = "1.2.0".freeze | |||
| VERSION = "1.3.0".freeze | |||
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| expect(GoTransit.service_day_boundary_hour).to eq(4) | ||
| end | ||
|
|
||
| it "can be overridden via configure" do |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| @@ -0,0 +1,15 @@ | |||
| RSpec.describe GoTransit do | |||
| describe ".service_day_boundary_hour" do | |||
| it "defaults to 4" do | |||
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| @@ -0,0 +1,15 @@ | |||
| RSpec.describe GoTransit do | |||
| describe ".service_day_boundary_hour" do | |||
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| @@ -0,0 +1,15 @@ | |||
| RSpec.describe GoTransit do | |||
There was a problem hiding this comment.
Style/FrozenStringLiteralComment: Missing magic comment # frozen_string_literal: true.
| it "cascades the anchor date to both arrival_time and departure_time" do | ||
| stop = described_class.new( | ||
| "ArrivalTime" => { "Scheduled" => "14:50", "Computed" => "", "Status" => "" }, | ||
| "DepartureTime" => { "Scheduled" => "14:54", "Computed" => "", "Status" => "" }, |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
Metrics/LineLength: Line is too long. [88/80]
Style/TrailingCommaInArguments: Avoid comma after the last parameter of a method call.
| describe "#anchor_date=" do | ||
| it "cascades the anchor date to both arrival_time and departure_time" do | ||
| stop = described_class.new( | ||
| "ArrivalTime" => { "Scheduled" => "14:50", "Computed" => "", "Status" => "" }, |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
Metrics/LineLength: Line is too long. [86/80]
| @@ -0,0 +1,15 @@ | |||
| RSpec.describe GoTransit::Schedule::Trip::Stop do | |||
| describe "#anchor_date=" do | |||
| it "cascades the anchor date to both arrival_time and departure_time" do | |||
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| @@ -0,0 +1,15 @@ | |||
| RSpec.describe GoTransit::Schedule::Trip::Stop do | |||
| describe "#anchor_date=" do | |||
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| @@ -0,0 +1,15 @@ | |||
| RSpec.describe GoTransit::Schedule::Trip::Stop do | |||
There was a problem hiding this comment.
Style/FrozenStringLiteralComment: Missing magic comment # frozen_string_literal: true.
|
|
||
| it "propagates its own Date to every stop, across every service and trip" do | ||
| date = Date.parse("2023-03-13") | ||
| journeys = GoTransit::Schedule.journey(date: date, from_stop_code: "UN", |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| end | ||
|
|
||
| it "propagates its own Date to every stop, across every service and trip" do | ||
| date = Date.parse("2023-03-13") |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| to be_kind_of(GoTransit::Schedule::Journey::SchJourney) | ||
| end | ||
|
|
||
| it "propagates its own Date to every stop, across every service and trip" do |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| it "raises MissingAnchorDateError when anchor_date was never assigned" do | ||
| stop = described_class.new(time: "07:00") | ||
|
|
||
| expect { stop.time_local }.to raise_error(GoTransit::MissingAnchorDateError) |
There was a problem hiding this comment.
Metrics/LineLength: Line is too long. [82/80]
| expect(stop.time_local.to_date).to eq(Date.new(2026, 1, 2)) | ||
| end | ||
|
|
||
| it "raises MissingAnchorDateError when anchor_date was never assigned" do |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| end | ||
|
|
||
| it "raises MissingAnchorDateError when anchor_date was never assigned" do | ||
| stop = GoTransit::Schedule::Journey::SchJourney::Service::Trip::Stop.new(time: "07:00") |
There was a problem hiding this comment.
Metrics/LineLength: Line is too long. [93/80]
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| end | ||
|
|
||
| it "rolls forward past the boundary hour, same rule as Schedule::Trip's stops" do | ||
| stop = GoTransit::Schedule::Journey::SchJourney::Service::Trip::Stop.new(time: "00:15") |
There was a problem hiding this comment.
Metrics/LineLength: Line is too long. [93/80]
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| expect(stop.time_utc).to eq(stop.time_local.utc) | ||
| end | ||
|
|
||
| it "rolls forward past the boundary hour, same rule as Schedule::Trip's stops" do |
There was a problem hiding this comment.
Metrics/LineLength: Line is too long. [85/80]
|
|
||
| describe "#time_local and #time_utc" do | ||
| it "resolve using the assigned anchor_date" do | ||
| stop = GoTransit::Schedule::Journey::SchJourney::Service::Trip::Stop.new(time: "07:00") |
There was a problem hiding this comment.
Metrics/LineLength: Line is too long. [93/80]
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| end | ||
|
|
||
| describe "#time_local and #time_utc" do | ||
| it "resolve using the assigned anchor_date" do |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
|
|
||
| describe "#scheduled_utc" do | ||
| it "converts the resolved local time to UTC" do | ||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "14:54") |
There was a problem hiding this comment.
Metrics/LineLength: Line is too long. [89/80]
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| end | ||
|
|
||
| describe "#scheduled_utc" do | ||
| it "converts the resolved local time to UTC" do |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| end | ||
| end | ||
|
|
||
| describe "#scheduled_utc" do |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| it "raises MissingAnchorDateError when anchor_date was never assigned" do | ||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "14:54") | ||
|
|
||
| expect { arrival_time.scheduled_local }. |
There was a problem hiding this comment.
Layout/DotPosition: Place the . on the next line, together with the method name.
| end | ||
|
|
||
| it "raises MissingAnchorDateError when anchor_date was never assigned" do | ||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "14:54") |
There was a problem hiding this comment.
Metrics/LineLength: Line is too long. [89/80]
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
The previous change added _utc/_local to every date and time field across the gem except two families that are returned as a bare "HH:MM", no date at all. Converting one of these to a real Time requires knowing which calendar date it belongs to, and GO Transit's own service date doesn't line up with calendar midnight: a service date starting at 6am can run past 2am the next calendar day, and every stop in that overnight tail still belongs to the original service date, not the next one. This change addresses the need by: * Adding a configurable service_day_boundary_hour (default 4) marking where one service date ends and the next begins * Resolving _utc/_local for these fields by anchoring to a known date rather than assuming "today", correctly handling a trip whose very first stop is already past midnight with no other stop to compare it against * Threading the anchor date through Schedule.trip and Schedule.journey automatically, so no caller has to supply one themselves
b94ac48 to
06781d0
Compare
| expect(arrival_time.scheduled_local).to be_nil | ||
| end | ||
|
|
||
| it "raises MissingAnchorDateError when anchor_date was never assigned" do |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| end | ||
|
|
||
| it "returns nil when the underlying field is blank" do | ||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "") |
There was a problem hiding this comment.
Metrics/LineLength: Line is too long. [84/80]
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| GoTransit.service_day_boundary_hour = original_boundary_hour | ||
| end | ||
|
|
||
| it "returns nil when the underlying field is blank" do |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| it "honors a custom service_day_boundary_hour" do | ||
| original_boundary_hour = GoTransit.service_day_boundary_hour | ||
| GoTransit.service_day_boundary_hour = 3 | ||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "03:30") |
There was a problem hiding this comment.
Metrics/LineLength: Line is too long. [89/80]
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| expect(result.to_date).to eq(Date.new(2026, 1, 2)) | ||
| end | ||
|
|
||
| it "honors a custom service_day_boundary_hour" do |
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| RSpec.describe GoTransit::Schedule::Trip::Stop::ArrivalTime do | ||
| describe "#scheduled_local" do | ||
| it "stays on the anchor date when the hour is at or after the boundary" do | ||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "23:58") |
There was a problem hiding this comment.
Metrics/LineLength: Line is too long. [89/80]
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| @@ -0,0 +1,82 @@ | |||
| RSpec.describe GoTransit::Schedule::Trip::Stop::ArrivalTime do | |||
| describe "#scheduled_local" do | |||
| it "stays on the anchor date when the hour is at or after the boundary" do | |||
There was a problem hiding this comment.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| @@ -0,0 +1,82 @@ | |||
| RSpec.describe GoTransit::Schedule::Trip::Stop::ArrivalTime do | |||
| describe "#scheduled_local" do | |||
There was a problem hiding this comment.
Metrics/BlockLength: Block has too many lines. [38/25]
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
| @@ -0,0 +1,82 @@ | |||
| RSpec.describe GoTransit::Schedule::Trip::Stop::ArrivalTime do | |||
There was a problem hiding this comment.
Metrics/BlockLength: Block has too many lines. [56/25]
Style/FrozenStringLiteralComment: Missing magic comment # frozen_string_literal: true.
| it "raises MissingAnchorDateError" do | ||
| departure_time = GoTransit::Schedule::Trip::Stop::DepartureTime.new(scheduled: "14:54") | ||
|
|
||
| expect { departure_time.scheduled_local }. |
There was a problem hiding this comment.
Layout/DotPosition: Place the . on the next line, together with the method name.
The previous change added _utc/_local to every date and time field
across the gem except two families that are returned as a bare
"HH:MM", no date at all. Converting one of these to a real Time
requires knowing which calendar date it belongs to, and GO Transit's
own service date doesn't line up with calendar midnight: a service
date starting at 6am can run past 2am the next calendar day, and
every stop in that overnight tail still belongs to the original
service date, not the next one.
This change addresses the need by:
where one service date ends and the next begins
date rather than assuming "today", correctly handling a trip whose
very first stop is already past midnight with no other stop to
compare it against
Schedule.journey automatically, so no caller has to supply one
themselves