Fix text product start time when first P-VTEC uses 000000T0000Z

This commit is contained in:
Dan Paulat 2023-05-29 00:47:47 -05:00
parent 58a2d8982a
commit 45b0df3e0b
3 changed files with 90 additions and 5 deletions

View file

@ -91,11 +91,14 @@ public:
std::shared_ptr<WmoHeader> wmo_header() const;
std::vector<std::string> mnd_header() const;
std::vector<std::string> overview_block() const;
size_t segment_count() const;
std::size_t segment_count() const;
std::vector<std::shared_ptr<const Segment>> segments() const;
std::shared_ptr<const Segment> segment(size_t s) const;
std::shared_ptr<const Segment> segment(std::size_t s) const;
size_t data_size() const;
std::chrono::system_clock::time_point
segment_event_begin(std::size_t s) const;
std::size_t data_size() const;
bool Parse(std::istream& is) override;

View file

@ -1,5 +1,6 @@
#include <scwx/awips/text_product_message.hpp>
#include <scwx/common/characters.hpp>
#include <scwx/util/logger.hpp>
#include <scwx/util/streams.hpp>
#include <istream>
@ -15,6 +16,7 @@ namespace awips
{
static const std::string logPrefix_ = "scwx::awips::text_product_message";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
// Issuance date/time takes one of the following forms:
// * <hhmm>_xM_<tz>_day_mon_<dd>_year
@ -101,6 +103,87 @@ std::shared_ptr<const Segment> TextProductMessage::segment(size_t s) const
return p->segments_[s];
}
std::chrono::system_clock::time_point
TextProductMessage::segment_event_begin(std::size_t s) const
{
std::chrono::system_clock::time_point eventBegin {};
auto& header = segment(s)->header_;
if (header.has_value() && !header->vtecString_.empty())
{
// Determine event begin from P-VTEC string
eventBegin = header->vtecString_[0].pVtec_.event_begin();
// If event begin is 000000T0000Z
if (eventBegin == std::chrono::system_clock::time_point {})
{
using namespace std::chrono;
// Determine event end from P-VTEC string
system_clock::time_point eventEnd =
header->vtecString_[0].pVtec_.event_end();
auto endDays = floor<days>(eventEnd);
year_month_day endDate {endDays};
// Determine WMO date/time
std::string wmoDateTime = wmo_header()->date_time();
bool wmoDateTimeValid = false;
unsigned long dayOfMonth = 0;
unsigned long beginHour = 0;
unsigned long beginMinute = 0;
try
{
// WMO date time is in the format DDHHMM
dayOfMonth = std::stoul(wmoDateTime.substr(0, 2));
beginHour = std::stoul(wmoDateTime.substr(2, 2));
beginMinute = std::stoul(wmoDateTime.substr(4, 2));
wmoDateTimeValid = true;
}
catch (const std::exception&)
{
logger_->warn("Malformed WMO date/time: {}", wmoDateTime);
}
if (wmoDateTimeValid)
{
// Combine end date year and month with WMO date time
eventBegin =
sys_days {endDate.year() / endDate.month() / day {dayOfMonth}} +
hours {beginHour} + minutes {beginMinute};
// If the begin date is after the end date, assume the start time
// was the previous month
if (eventBegin > eventEnd)
{
// If the current end month is January
if (endDate.month() == January)
{
// The begin month must be December of last year
eventBegin = sys_days {year {(endDate.year() - 1y).count()} /
December / day {dayOfMonth}} +
hours {beginHour} + minutes {beginMinute};
}
else
{
// Back up one month
eventBegin =
sys_days {endDate.year() /
month {static_cast<unsigned int>(
(endDate.month() - month {1}).count())} /
day {dayOfMonth}} +
hours {beginHour} + minutes {beginMinute};
}
}
}
}
}
return eventBegin;
}
size_t TextProductMessage::data_size() const
{
return 0;