From b19b886e76dee4f7a2836c30720cfd32bf8d6916 Mon Sep 17 00:00:00 2001 From: Ian Kluft Date: Wed, 3 Jul 2024 22:56:18 -0700 Subject: [PATCH] reorg constructors to use initializers --- src/cpp/libtzsolar/libtzsolar/libtzsolar.cpp | 40 ++++++++++---------- src/cpp/libtzsolar/libtzsolar/libtzsolar.hpp | 25 +++++++----- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/cpp/libtzsolar/libtzsolar/libtzsolar.cpp b/src/cpp/libtzsolar/libtzsolar/libtzsolar.cpp index 0572b35..692012f 100644 --- a/src/cpp/libtzsolar/libtzsolar/libtzsolar.cpp +++ b/src/cpp/libtzsolar/libtzsolar/libtzsolar.cpp @@ -74,11 +74,14 @@ std::string ltz::TZSolar::tz_name ( const unsigned short tz_num, const bool use_ } // check latitude data and initialize special case for polar regions - internal method called by tz_params() -bool ltz::TZSolar::tz_params_latitude ( const bool use_lon_tz, const float latitude ) { +bool ltz::TZSolar::tz_params_latitude () { + if ( !opt_latitude.has_value()) { + return false; + } + // special case: use East00/Lon000E (equal to UTC) within 10° latitude of poles - if ( std::abs( latitude ) >= limit_latitude - precision_fp ) { + if ( std::abs( opt_latitude.value() ) >= limit_latitude - precision_fp ) { // note: for polar latitudes, this must set all fields on behalf of the constructor - lon_tz = use_lon_tz; short_name = lon_tz ? "Lon000E" : "East00"; return true; } @@ -87,10 +90,10 @@ bool ltz::TZSolar::tz_params_latitude ( const bool use_lon_tz, const float latit } // get timezone parameters (name and minutes offset) - called by constructor -void ltz::TZSolar::tz_params (const float lon, const bool use_lon_tz, const std::optional opt_latitude ) { +void ltz::TZSolar::tz_params () { // if latitude is provided, use UTC within 10° latitude of poles if ( opt_latitude.has_value() ) { - if ( this->tz_params_latitude( use_lon_tz, opt_latitude.value() )) { + if ( this->tz_params_latitude()) { return; } // fall through if latitude was provided but not in the extreme polar regions (so ignore it) @@ -101,27 +104,22 @@ void ltz::TZSolar::tz_params (const float lon, const bool use_lon_tz, const std: // // safety check on longitude - if ( std::abs( lon ) > max_longitude_fp + precision_fp ) { + if ( std::abs( longitude ) > max_longitude_fp + precision_fp ) { throw std::out_of_range( "longitude out of range -180 to +180" ); } - this->longitude = lon; - - // set flag for longitude time zones: 0 = hourly 1-hour/15-degree zones, 1 = longitude 4-minute/1-degree zones - // defaults to hourly time zone ($use_lon_tz=0) - lon_tz = use_lon_tz; // handle special case of half-wide tz at positive side of solar date line (180° longitude) if (( longitude >= max_longitude_int - this->tz_degree_width() / 2.0 - precision_fp ) || ( longitude <= -max_longitude_int + precision_fp )) { - short_name = tz_name(( unsigned short )( max_longitude_int / tz_degree_width()), use_lon_tz, 1 ); + short_name = tz_name(( unsigned short )( max_longitude_int / tz_degree_width()), lon_tz, 1 ); offset_min = 720; return; } // handle special case of half-wide tz at negative side of solar date line (180° longitude) if ( longitude <= -max_longitude_int + this->tz_degree_width() / 2.0 + precision_fp ) { - short_name = tz_name(( unsigned short)( max_longitude_int / tz_degree_width()), use_lon_tz, -1 ); + short_name = tz_name(( unsigned short)( max_longitude_int / tz_degree_width()), lon_tz, -1 ); offset_min = -720; return; } @@ -130,7 +128,7 @@ void ltz::TZSolar::tz_params (const float lon, const bool use_lon_tz, const std: unsigned short tz_num = ( unsigned short )( std::abs (( double ) longitude) / tz_degree_width() + 0.5 + precision_fp ); short sign = ( longitude > -tz_degree_width() / 2.0 + precision_fp ) ? 1 : -1; - short_name = tz_name( tz_num, use_lon_tz, sign ); + short_name = tz_name( tz_num, lon_tz, sign ); offset_min = sign * tz_num * minutes_per_degree_lon * tz_degree_width(); } @@ -144,9 +142,9 @@ ltz::TZSolar::TZSolar( const std::string &tzname ) { // use regex to check for longitude-based time zone (like Lon180E, Lon123W) if (std::regex_search(tzname_lower, tzsolar_lon_zone_re)) { bool is_west = tzname_lower.at(6) == 'w'; - float lon = boost::numeric_cast(std::stof(tzname_lower.substr(3,3)) * (is_west ? -1 : 1)); - bool use_lon_tz = true; - this->tz_params(lon, use_lon_tz, std::nullopt); + longitude = boost::numeric_cast(std::stof(tzname_lower.substr(3,3)) * (is_west ? -1 : 1)); + lon_tz = true; + this->tz_params(); return; } @@ -154,9 +152,9 @@ ltz::TZSolar::TZSolar( const std::string &tzname ) { if (std::regex_search(tzname_lower, tzsolar_hour_zone_re)) { bool is_west = tzname_lower.substr(0,4) == "west"; short hour_num = boost::numeric_cast(std::stoi(tzname_lower.substr(4,2))); - float lon = boost::numeric_cast(hour_num * 15 * (is_west ? -1 : 1)); - bool use_lon_tz = false; - this->tz_params(lon, use_lon_tz, std::nullopt); + longitude = boost::numeric_cast(hour_num * 15 * (is_west ? -1 : 1)); + lon_tz = false; + this->tz_params(); return; } @@ -199,7 +197,7 @@ const std::optional ltz::TZSolar::get(const std::string &field) { // non-existent field results in a blank response if (!funcmap.count(field)) { - return nullptr; + return std::nullopt; } // call function to get field value, or throw std::out_of_range exception for unrecognized field diff --git a/src/cpp/libtzsolar/libtzsolar/libtzsolar.hpp b/src/cpp/libtzsolar/libtzsolar/libtzsolar.hpp index f5ad573..0cc04f5 100644 --- a/src/cpp/libtzsolar/libtzsolar/libtzsolar.hpp +++ b/src/cpp/libtzsolar/libtzsolar/libtzsolar.hpp @@ -11,6 +11,8 @@ namespace longitude_tz { // solar time zones class + // This serves as a base class for multiple library implementations. + // This can be used standalone for testing. class TZSolar { public: @@ -30,18 +32,19 @@ namespace longitude_tz { static const int limit_latitude; static const int minutes_per_degree_lon; - // private class-static data private: + + // class-static data static bool debug_flag; // member data - protected: - - std::string short_name; // time zone base name, i.e. Lon000E or East00 - bool lon_tz; // flag: use longitude timezones; if false defaults to hour-based time zones - int offset_min; // time zone offset in minutes float longitude; // longitude for time zone position + bool lon_tz; // flag: use longitude timezones: false defaults to hour-based tz, true = degree-based tz std::optional opt_latitude; // optional latitude for computing polar exclusion + int offset_min; // time zone offset in minutes + std::string short_name; // time zone base name, i.e. Lon000E or East00 + + protected: // // protected methods @@ -54,10 +57,10 @@ namespace longitude_tz { static std::string tz_name ( const unsigned short tz_num, const bool use_lon_tz, const short sign ); // get timezone parameters (name and minutes offset) - called by constructor - bool tz_params_latitude ( const bool use_lon_tz, const float latitude ); + bool tz_params_latitude (); // get timezone parameters (name and minutes offset) - called by constructor - void tz_params (const float longitude, const bool use_lon_tz, const std::optional opt_latitude ); + void tz_params (); public: @@ -67,8 +70,10 @@ namespace longitude_tz { const static inline void debug_print(const std::string &msg) { if (debug_flag) { std::cerr << msg << std::endl; } } // constructor from time zone parameters - TZSolar( const float longitude, const bool use_lon_tz, const std::optional latitude ) { - this->tz_params( longitude, use_lon_tz, latitude ); + TZSolar( const float lon_in, const bool lon_tz_in, const std::optional lat_in = std::nullopt ) + : longitude(lon_in), lon_tz(lon_tz_in), opt_latitude(lat_in) + { + this->tz_params(); } // constructor from time zone name