mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 12:00:04 +00:00 
			
		
		
		
	Fix text product start time when first P-VTEC uses 000000T0000Z
This commit is contained in:
		
							parent
							
								
									58a2d8982a
								
							
						
					
					
						commit
						45b0df3e0b
					
				
					 3 changed files with 90 additions and 5 deletions
				
			
		|  | @ -421,8 +421,7 @@ AlertModelImpl::GetStartTime(const types::TextEventKey& key) | ||||||
|    if (messageList.size() > 0) |    if (messageList.size() > 0) | ||||||
|    { |    { | ||||||
|       auto& firstMessage = messageList.front(); |       auto& firstMessage = messageList.front(); | ||||||
|       auto  firstSegment = firstMessage->segment(0); |       return firstMessage->segment_event_begin(0); | ||||||
|       return firstSegment->header_->vtecString_[0].pVtec_.event_begin(); |  | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|  |  | ||||||
|  | @ -91,11 +91,14 @@ public: | ||||||
|    std::shared_ptr<WmoHeader>                  wmo_header() const; |    std::shared_ptr<WmoHeader>                  wmo_header() const; | ||||||
|    std::vector<std::string>                    mnd_header() const; |    std::vector<std::string>                    mnd_header() const; | ||||||
|    std::vector<std::string>                    overview_block() 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::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; |    bool Parse(std::istream& is) override; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| #include <scwx/awips/text_product_message.hpp> | #include <scwx/awips/text_product_message.hpp> | ||||||
| #include <scwx/common/characters.hpp> | #include <scwx/common/characters.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
| #include <scwx/util/streams.hpp> | #include <scwx/util/streams.hpp> | ||||||
| 
 | 
 | ||||||
| #include <istream> | #include <istream> | ||||||
|  | @ -15,6 +16,7 @@ namespace awips | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| static const std::string logPrefix_ = "scwx::awips::text_product_message"; | 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:
 | // Issuance date/time takes one of the following forms:
 | ||||||
| // * <hhmm>_xM_<tz>_day_mon_<dd>_year
 | // * <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]; |    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 | size_t TextProductMessage::data_size() const | ||||||
| { | { | ||||||
|    return 0; |    return 0; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat