-
Notifications
You must be signed in to change notification settings - Fork 0
Add Time Only Local and UTC Helpers #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| coverage | ||
| pkg/ | ||
| .m/ | ||
| .worktrees/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| PATH | ||
| remote: . | ||
| specs: | ||
| go_transit (1.2.0) | ||
| go_transit (1.3.0) | ||
| activesupport | ||
|
|
||
| GEM | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,5 +48,25 @@ def to_utc(date) | |
| def to_local(date, timezone: "America/Toronto") | ||
| date.in_time_zone(timezone) | ||
| end | ||
|
|
||
| def to_utc_from_anchor(time, trip_date, timezone: "America/Toronto") | ||
| 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| raise MissingAnchorDateError if trip_date.nil? | ||
| return nil if time.blank? | ||
| hour = time.split(":").first.to_i | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| date = determine_date(trip_date, hour) | ||
| "#{date} #{time}".in_time_zone(timezone) | ||
| end | ||
|
|
||
| def determine_date(date, hour) | ||
| if hour < GoTransit.service_day_boundary_hour | ||
| date + 1.day | ||
| else | ||
| date | ||
| end | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,21 @@ | ||
| module GoTransit | ||
| class Schedule::Journey::SchJourney < ApiResource | ||
| attr_accessor :date, :time, :to, :from, :services | ||
|
|
||
| def initialize(params) | ||
| super | ||
| propagate_anchor_date | ||
| end | ||
|
|
||
| private | ||
|
|
||
| def propagate_anchor_date | ||
| parsed_date = Date.parse(date) | ||
| services.each do |service| | ||
| service.trips.each do |trip| | ||
| trip.stops.each { |stop| stop.anchor_date = parsed_date } | ||
| end | ||
| end | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,17 @@ | ||
| module GoTransit | ||
| class Schedule::Journey::SchJourney::Service::Trip::Stop < ApiResource | ||
| attr_accessor :code, :order, :time, :sorting_time, :is_major | ||
| attr_accessor :code, :order, :time, :sorting_time, :is_major, :anchor_date | ||
|
|
||
| def major? | ||
| is_major.to_i.positive? | ||
| end | ||
|
|
||
| def time_utc | ||
| to_utc_from_anchor(time, anchor_date) | ||
| end | ||
|
|
||
| def time_local | ||
| to_local_from_anchor(time, anchor_date) | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,21 @@ | ||
| module GoTransit | ||
| class Schedule::Trip::Stop::ArrivalTime < ApiResource | ||
| attr_accessor :scheduled, :computed, :status | ||
| attr_accessor :scheduled, :computed, :status, :anchor_date | ||
|
|
||
| def scheduled_utc | ||
| to_utc_from_anchor(scheduled, anchor_date) | ||
| end | ||
|
|
||
| def scheduled_local | ||
| to_local_from_anchor(scheduled, anchor_date) | ||
| end | ||
|
|
||
| def computed_utc | ||
| to_utc_from_anchor(computed, anchor_date) | ||
| end | ||
|
|
||
| def computed_local | ||
| to_local_from_anchor(computed, anchor_date) | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,21 @@ | ||
| module GoTransit | ||
| class Schedule::Trip::Stop::DepartureTime < ApiResource | ||
| attr_accessor :scheduled, :computed, :status | ||
| attr_accessor :scheduled, :computed, :status, :anchor_date | ||
|
|
||
| def scheduled_utc | ||
| to_utc_from_anchor(scheduled, anchor_date) | ||
| end | ||
|
|
||
| def scheduled_local | ||
| to_local_from_anchor(scheduled, anchor_date) | ||
| end | ||
|
|
||
| def computed_utc | ||
| to_utc_from_anchor(computed, anchor_date) | ||
| end | ||
|
|
||
| def computed_local | ||
| to_local_from_anchor(computed, anchor_date) | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| module GoTransit | ||
| VERSION = "1.2.0".freeze | ||
| VERSION = "1.3.0".freeze | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| RSpec.describe GoTransit do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/FrozenStringLiteralComment: Missing magic comment # frozen_string_literal: true. |
||
| describe ".service_day_boundary_hour" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| it "defaults to 4" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| GoTransit.configure { |config| config.service_day_boundary_hour = 3 } | ||
|
|
||
| expect(GoTransit.service_day_boundary_hour).to eq(3) | ||
|
|
||
| GoTransit.configure { |config| config.service_day_boundary_hour = 4 } | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,4 +20,27 @@ | |
| end | ||
| end | ||
| end | ||
|
|
||
| describe "#time_local and #time_utc" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| it "resolve using the assigned anchor_date" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| stop = GoTransit::Schedule::Journey::SchJourney::Service::Trip::Stop.new(time: "07:00") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [93/80] |
||
| stop.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| expect(stop.time_local.to_date).to eq(Date.new(2026, 1, 1)) | ||
| 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [85/80] |
||
| stop = GoTransit::Schedule::Journey::SchJourney::Service::Trip::Stop.new(time: "00:15") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [93/80] |
||
| stop.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| stop = GoTransit::Schedule::Journey::SchJourney::Service::Trip::Stop.new(time: "07:00") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [93/80] |
||
|
|
||
| expect { stop.time_local }.to raise_error(GoTransit::MissingAnchorDateError) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [82/80] |
||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| RSpec.describe GoTransit::Schedule::Trip::Stop::ArrivalTime do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/BlockLength: Block has too many lines. [56/25] |
||
| describe "#scheduled_local" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/BlockLength: Block has too many lines. [38/25] |
||
| it "stays on the anchor date when the hour is at or after the boundary" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "23:58") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [89/80] |
||
| arrival_time.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| result = arrival_time.scheduled_local | ||
|
|
||
| expect(result).to eq(Date.new(2026, 1, 1).in_time_zone("America/Toronto") + 23.hours + 58.minutes) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| end | ||
|
|
||
| it "rolls forward to the next day when the hour is before the boundary" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "00:04") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [89/80] |
||
| arrival_time.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| result = arrival_time.scheduled_local | ||
|
|
||
| expect(result).to eq(Date.new(2026, 1, 2).in_time_zone("America/Toronto") + 4.minutes) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| end | ||
|
|
||
| it "rolls forward even when it is the trip's very first stop, with no prior stop to compare against" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [107/80] |
||
| # This is the whole point of a fixed boundary hour rather than | ||
| # sequence-based rollover detection: a trip whose first stop is | ||
| # already in the "overnight tail" of the previous service date | ||
| # rolls forward correctly with no other stop involved at all. | ||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "01:00") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [89/80] |
||
| arrival_time.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| result = arrival_time.scheduled_local | ||
|
|
||
| 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [89/80] |
||
| arrival_time.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| result = arrival_time.scheduled_local | ||
|
|
||
| expect(result.to_date).to eq(Date.new(2026, 1, 1)) | ||
| ensure | ||
| 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [84/80] |
||
| arrival_time.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "14:54") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [89/80] |
||
|
|
||
| expect { arrival_time.scheduled_local }. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Layout/DotPosition: Place the . on the next line, together with the method name. |
||
| to raise_error(GoTransit::MissingAnchorDateError) | ||
| end | ||
| end | ||
|
|
||
| describe "#scheduled_utc" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| it "converts the resolved local time to UTC" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "14:54") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [89/80] |
||
| arrival_time.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| result = arrival_time.scheduled_utc | ||
|
|
||
| expect(result).to eq(Date.new(2026, 1, 1).in_time_zone("America/Toronto").utc + 14.hours + 54.minutes) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| end | ||
| end | ||
|
|
||
| describe "#computed_local and #computed_utc" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| it "resolve the same way as scheduled, independently" do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| arrival_time = GoTransit::Schedule::Trip::Stop::ArrivalTime.new(scheduled: "14:54", computed: "15:01") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/LineLength: Line is too long. [108/80] |
||
| arrival_time.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| expect(arrival_time.computed_local.strftime("%H:%M")).to eq("15:01") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. |
||
| expect(arrival_time.computed_utc).to eq(arrival_time.computed_local.utc) | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| RSpec.describe GoTransit::Schedule::Trip::Stop::DepartureTime do | ||
| describe "#scheduled_local and #scheduled_utc" do | ||
| it "resolve using the assigned anchor_date, same as ArrivalTime" do | ||
| departure_time = GoTransit::Schedule::Trip::Stop::DepartureTime.new(scheduled: "00:04") | ||
| departure_time.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| expect(departure_time.scheduled_local.to_date).to eq(Date.new(2026, 1, 2)) | ||
| expect(departure_time.scheduled_utc).to eq(departure_time.scheduled_local.utc) | ||
| end | ||
| end | ||
|
|
||
| describe "#computed_local and #computed_utc" do | ||
| it "resolve independently of scheduled" do | ||
| departure_time = GoTransit::Schedule::Trip::Stop::DepartureTime.new(computed: "14:54") | ||
| departure_time.anchor_date = Date.new(2026, 1, 1) | ||
|
|
||
| expect(departure_time.computed_local.strftime("%H:%M")).to eq("14:54") | ||
| end | ||
| end | ||
|
|
||
| describe "without an anchor_date" do | ||
| 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Layout/DotPosition: Place the . on the next line, together with the method name. |
||
| to raise_error(GoTransit::MissingAnchorDateError) | ||
| end | ||
| end | ||
| end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.