Skip to content

Commit

Permalink
Mjolnir date time (valhalla#1432)
Browse files Browse the repository at this point in the history
* Separate out service day logic from DateTime and put in mjolnir since it
is only used when bulding data. This removes some boost functionality from
the regular build. Separate servicedays tests as well.

* Updates to move more methods out of DateTime into mjolnir

* Separate out time parsing into its own file in mjolnir.

* Replace boost::remove_if with std::remove_if. Move one seconds_to_date method to
the test code since it was not used outside of the tests. Update some comments.

* Fix comment.
  • Loading branch information
dnesbitt61 committed Jul 23, 2018
1 parent 4dc6235 commit acd77ea
Show file tree
Hide file tree
Showing 14 changed files with 1,743 additions and 1,671 deletions.
895 changes: 10 additions & 885 deletions src/baldr/datetime.cc

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/mjolnir/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ set(sources
pbfadminparser.cc
pbfgraphparser.cc
restrictionbuilder.cc
servicedays.cc
shortcutbuilder.cc
timeparsing.cc
transitbuilder.cc
util.cc
validatetransit.cc)
Expand Down
5 changes: 3 additions & 2 deletions src/mjolnir/pbfgraphparser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "midgard/polyline2.h"
#include "midgard/sequence.h"
#include "midgard/tiles.h"
#include "mjolnir/servicedays.h"

using namespace valhalla::midgard;
using namespace valhalla::baldr;
Expand Down Expand Up @@ -669,7 +670,7 @@ struct graph_callback : public OSMPBF::Callback {
std::vector<std::string> conditions = GetTagTokens(tmp, ';');

for (const auto& condition : conditions) {
std::vector<uint64_t> values = DateTime::get_time_range(condition);
std::vector<uint64_t> values = get_time_range(condition);

for (const auto& v : values) {
OSMAccessRestriction restriction;
Expand Down Expand Up @@ -1440,7 +1441,7 @@ struct graph_callback : public OSMPBF::Callback {
}

for (const auto& c : conditions) {
std::vector<uint64_t> values = DateTime::get_time_range(c);
std::vector<uint64_t> values = get_time_range(c);
for (const auto& v : values) { // could have multiple time domains
restriction.set_time_domain(v);
complex_restrictions_->push_back(restriction);
Expand Down
144 changes: 144 additions & 0 deletions src/mjolnir/servicedays.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

#include "baldr/datetime.h"
#include "mjolnir/servicedays.h"

using namespace valhalla::baldr;
using namespace valhalla::mjolnir;

namespace valhalla {
namespace mjolnir {

// Get a formatted testing date. Currently, next Tuesday @ 08:00.
std::string get_testing_date_time() {
auto tz = DateTime::get_tz_db().from_index(DateTime::get_tz_db().to_index("America/New_York"));
boost::gregorian::date d = DateTime::get_formatted_date(DateTime::iso_date_time(tz));

while (d.day_of_week() != boost::date_time::Tuesday) {
d += boost::gregorian::days(1);
}

return to_iso_extended_string(d) + "T08:00";
}

// Get the days that this transit service is running in 60 days or less
uint64_t get_service_days(boost::gregorian::date& start_date,
boost::gregorian::date& end_date,
const uint32_t tile_date,
const uint32_t dow_mask) {

boost::gregorian::date tile_header_date = pivot_date_ + boost::gregorian::days(tile_date);

// if our start date is more than 60 days out, reject.
if (start_date > (tile_header_date + boost::gregorian::days(59))) {
return 0;
}

if (start_date <= tile_header_date && tile_header_date <= end_date) {
start_date = tile_header_date;
} else if (tile_header_date > end_date) { // reject.
return 0;
}

// only support 60 days out. (59 days and include the end_date = 60)
boost::gregorian::date enddate = tile_header_date + boost::gregorian::days(59);

if (enddate <= end_date) {
end_date = enddate;
}

uint32_t days = 0;
boost::gregorian::day_iterator itr(tile_header_date + boost::gregorian::days(days));

uint32_t x = days;
uint64_t bit_set = 0;

// TODO: we dont have to loop over all days, we could take the week mask, shift it by the start
// date then use that weekly mask and shift it how ever many times a week fits into the 60 day
// interval loop over all the days
while (itr <= end_date) {

// figure out what day of the week we are at
uint8_t dow;
switch ((*itr).day_of_week().as_enum()) {
case boost::date_time::Sunday:
dow = kSunday;
break;
case boost::date_time::Monday:
dow = kMonday;
break;
case boost::date_time::Tuesday:
dow = kTuesday;
break;
case boost::date_time::Wednesday:
dow = kWednesday;
break;
case boost::date_time::Thursday:
dow = kThursday;
break;
case boost::date_time::Friday:
dow = kFriday;
break;
case boost::date_time::Saturday:
dow = kSaturday;
break;
}

// were we supposed to be on for this day?
// and are we at or after the start date?
if ((dow_mask & dow) && (itr >= start_date)) {
bit_set |= static_cast<uint64_t>(1) << x;
}

++itr;
++x;
}
return bit_set;
}

// Adds a service day to the days.
uint64_t add_service_day(const uint64_t& days,
const boost::gregorian::date& end_date,
const uint32_t tile_date,
const boost::gregorian::date& added_date) {

// adding a service day must start at the tile header date.
boost::gregorian::date start_date = pivot_date_ + boost::gregorian::days(tile_date);
boost::gregorian::date enddate = start_date + boost::gregorian::days(59);

if (enddate > end_date) {
enddate = end_date;
}

if (start_date <= added_date && added_date <= enddate) {
boost::gregorian::date_period range(start_date, added_date);
uint32_t length = range.length().days();
return days | (static_cast<uint64_t>(1) << length);
}
return days;
}

// Removes a service day to the days.
uint64_t remove_service_day(const uint64_t& days,
const boost::gregorian::date& end_date,
const uint32_t tile_date,
const boost::gregorian::date& removed_date) {
// removing a service day must start at the tile header date.
boost::gregorian::date start_date = pivot_date_ + boost::gregorian::days(tile_date);
boost::gregorian::date enddate = start_date + boost::gregorian::days(59);

if (enddate > end_date) {
enddate = end_date;
}

if (start_date <= removed_date && removed_date <= enddate) {
boost::gregorian::date_period range(start_date, removed_date);
uint32_t length = range.length().days();
return ~((~days) | (static_cast<uint64_t>(1) << length));
}
return days;
}

} // namespace mjolnir
} // namespace valhalla
Loading

0 comments on commit acd77ea

Please sign in to comment.