Skip to content

Commit

Permalink
centralized time parsing (#164)
Browse files Browse the repository at this point in the history
  • Loading branch information
mority authored Jan 13, 2025
1 parent 4e158cd commit 0861ed9
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 29 deletions.
6 changes: 5 additions & 1 deletion include/nigiri/common/parse_time.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

namespace nigiri {

unixtime_t parse_time(std::string const&);
unixtime_t parse_time_tz(std::string_view s, char const* format);

unixtime_t parse_time(std::string_view s, char const* format);

unixtime_t parse_time_no_tz(std::string_view);

} // namespace nigiri
32 changes: 26 additions & 6 deletions src/common/parse_time.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,32 @@

namespace nigiri {

unixtime_t parse_time(std::string const& str) {
unixtime_t parsed;
auto ss = std::stringstream{str};
ss.exceptions(std::ios::badbit | std::ios::failbit | std::ios::eofbit);
ss >> date::parse("%FT%T", parsed);
return parsed;
unixtime_t parse_time_tz(std::string_view s, char const* format) {
std::stringstream in;
in.exceptions(std::ios::badbit | std::ios::failbit);
in << s;

date::local_seconds ls;
std::string tz;
in >> date::parse(format, ls, tz);

return std::chrono::time_point_cast<unixtime_t::duration>(
date::make_zoned(tz, ls).get_sys_time());
}

unixtime_t parse_time(std::string_view s, char const* format) {
std::stringstream in;
in.exceptions(std::ios::badbit | std::ios::failbit);
in << s;

unixtime_t u;
in >> date::parse(format, u);

return u;
}

unixtime_t parse_time_no_tz(std::string_view s) {
return parse_time(s, "%FT%T");
}

} // namespace nigiri
2 changes: 1 addition & 1 deletion src/rt/vdv/vdv_update.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ std::optional<unixtime_t> updater::get_opt_time(pugi::xml_node const& node,
auto const xpath = node.select_node(str);
if (xpath != nullptr) {
try {
return std::optional{parse_time(xpath.node().child_value())};
return std::optional{parse_time_no_tz(xpath.node().child_value())};
} catch (std::exception const& e) {
log(log_lvl::error, "vdv_update.get_opt_time",
"{}, invalid time input: {}", e.what(), xpath.node().child_value());
Expand Down
24 changes: 22 additions & 2 deletions test/parse_time_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,32 @@
using namespace nigiri;
using namespace date;

TEST(parse_time, invalid_time_tz) {
EXPECT_THROW(parse_time_tz("invalid", "%Y-%m-%d %H:%M %Z"), std::exception);
}

TEST(parse_time, valid_time_tz) {
EXPECT_EQ(
unixtime_t{date::sys_days{2000_y / January / 1} + 7_hours + 7_minutes},
parse_time_tz("2000-01-01 08:07 Europe/Berlin", "%Y-%m-%d %H:%M %Z"));
}

TEST(parse_time, invalid_time) {
EXPECT_THROW(parse_time("invalid"), std::exception);
EXPECT_THROW(parse_time("invalid", "%FT%T%z"), std::exception);
}

TEST(parse_time, valid_time) {
EXPECT_EQ(
unixtime_t{date::sys_days{2000_y / January / 1} + 7_hours + 7_minutes},
parse_time("2000-01-01T07:07:00"));
parse_time("2000-01-01T07:07:00+0000", "%FT%T%z"));
}

TEST(parse_time, invalid_time_no_tz) {
EXPECT_THROW(parse_time_no_tz("invalid"), std::exception);
}

TEST(parse_time, valid_time_no_tz) {
EXPECT_EQ(
unixtime_t{date::sys_days{2000_y / January / 1} + 7_hours + 7_minutes},
parse_time_no_tz("2000-01-01T07:07:00"));
}
20 changes: 5 additions & 15 deletions test/raptor_search.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "./raptor_search.h"

#include "nigiri/common/parse_time.h"
#include "nigiri/routing/limits.h"
#include "nigiri/routing/raptor/raptor.h"
#include "nigiri/routing/raptor_search.h"
Expand All @@ -8,18 +9,6 @@

namespace nigiri::test {

unixtime_t parse_time(std::string_view s, char const* format) {
std::stringstream in;
in << s;

date::local_seconds ls;
std::string tz;
in >> date::parse(format, ls, tz);

return std::chrono::time_point_cast<unixtime_t::duration>(
date::make_zoned(tz, ls).get_sys_time());
}

pareto_set<routing::journey> raptor_search(timetable const& tt,
rt_timetable const* rtt,
routing::query q,
Expand Down Expand Up @@ -64,8 +53,9 @@ pareto_set<routing::journey> raptor_search(timetable const& tt,
direction const search_dir,
routing::clasz_mask_t mask,
bool const require_bikes_allowed) {
return raptor_search(tt, rtt, from, to, parse_time(time, "%Y-%m-%d %H:%M %Z"),
search_dir, mask, require_bikes_allowed, 0U);
return raptor_search(tt, rtt, from, to,
parse_time_tz(time, "%Y-%m-%d %H:%M %Z"), search_dir,
mask, require_bikes_allowed, 0U);
}

pareto_set<routing::journey> raptor_search(timetable const& tt,
Expand All @@ -85,7 +75,7 @@ pareto_set<routing::journey> raptor_search(timetable const& tt,
{tt.locations_.location_id_to_idx_.at({to, src}), 0_minutes, 0U}};
}
if (!time.empty()) {
q.start_time_ = parse_time(time, "%Y-%m-%d %H:%M %Z");
q.start_time_ = parse_time_tz(time, "%Y-%m-%d %H:%M %Z");
}
return raptor_search(tt, rtt, std::move(q), search_dir);
}
Expand Down
2 changes: 0 additions & 2 deletions test/raptor_search.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ struct rt_timetable;

namespace nigiri::test {

unixtime_t parse_time(std::string_view s, char const* format);

pareto_set<routing::journey> raptor_search(
timetable const&,
rt_timetable const*,
Expand Down
5 changes: 3 additions & 2 deletions test/routing/via_search_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include "utl/erase_if.h"

#include "nigiri/common/parse_time.h"

#include "nigiri/loader/gtfs/agency.h"
#include "nigiri/loader/gtfs/calendar.h"
#include "nigiri/loader/gtfs/calendar_date.h"
Expand All @@ -26,7 +28,6 @@ using namespace nigiri;
using namespace date;
using namespace std::chrono_literals;
using namespace std::string_view_literals;
using nigiri::test::parse_time;
using nigiri::test::raptor_search;

namespace {
Expand Down Expand Up @@ -173,7 +174,7 @@ location_idx_t loc(timetable const& tt, std::string_view const id) {
}

unixtime_t time(std::string_view const time) {
return parse_time(time, "%Y-%m-%d %H:%M %Z");
return parse_time_tz(time, "%Y-%m-%d %H:%M %Z");
}

timetable load_timetable(std::string_view s) {
Expand Down

0 comments on commit 0861ed9

Please sign in to comment.