Skip to content

Commit

Permalink
Python: implement --tzname for CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
ikluft committed May 22, 2024
1 parent 262f17c commit 609e25e
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 8 deletions.
42 changes: 36 additions & 6 deletions src/python/scripts/lon_tz.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def _do_tzfile() -> None:


def _do_lon_tz(args: dict) -> ErrStr | None:
"""call timezone_solar to generate time zone from parmeters on command line"""
"""call TimeZoneSolar to generate time zone from parmeters on command line"""
err = None

# collect parameters
Expand All @@ -142,7 +142,7 @@ def _do_lon_tz(args: dict) -> ErrStr | None:
case "longitude":
tzs_params["use_lon_tz"] = True

# instantiate timezone_solar object and print requested field
# instantiate TimeZoneSolar object and print requested field(s)
tzs = TimeZoneSolar(**tzs_params)
try:
get_keys = (','.join(args["get"])).split(sep=',')
Expand All @@ -157,6 +157,27 @@ def _do_lon_tz(args: dict) -> ErrStr | None:

return err


def _do_named_tz(args: dict) -> ErrStr | None:
"""call TimeZoneSolar to generate date for a named time zone"""
err = None

# instantiate TimeZoneSolar object and print requested field(s)
tzname = args["tzname"]
tzs = TimeZoneSolar(tzname=tzname)
try:
get_keys = (','.join(args["get"])).split(sep=',')
for get_key in get_keys:
value = tzs.get(get_key)
if value is None:
print("")
else:
print(value)
except ValueError as tz_exc:
err = str(tz_exc)

return err

#
# command-line parsing functions
#
Expand Down Expand Up @@ -184,7 +205,7 @@ def _gen_arg_parser() -> argparse.ArgumentParser:
help="turn on debugging mode",
)

# mutually-exclusive arguments: --tzfile and --longitude
# mutually-exclusive arguments: --tzfile, --tzname and --longitude
excl_group = top_parser.add_mutually_exclusive_group(required=True)

# --tzfile/tzdata flag triggers output of tzdata file and ends program
Expand All @@ -195,14 +216,21 @@ def _gen_arg_parser() -> argparse.ArgumentParser:
help="generate solar time zones tzdata text",
)

# --tzname sets a name for a specified time zone, no other parameters allowed when this is used
excl_group.add_argument(
"--tzname",
type=str,
help="name of a specific solar time zone (mutually exclusive with --tzfile & --longitude)",
)

# --longitude sets degrees of longitude for a specified time zone
excl_group.add_argument(
"--longitude",
type=float,
help="longitude for solar time zone (required when not using --tzfile)",
help="longitude for solar time zone (mutually exclusive with --tzfile & --tzname)",
)

# parameters for timezone_solar
# parameters for TimeZoneSolar
top_parser.add_argument(
"--latitude",
type=float,
Expand All @@ -218,7 +246,7 @@ def _gen_arg_parser() -> argparse.ArgumentParser:
top_parser.add_argument(
"--get",
action='append',
help="specify solar time zone field to output",
help="specify solar time zone field(s) for output",
)

return top_parser
Expand Down Expand Up @@ -249,6 +277,8 @@ def main():
# call function named in argument parser settings with a dictionary of the CLI arguments
if "tzfile" in args and args["tzfile"] is True:
_do_tzfile()
elif "tzname" in args and args["tzname"] is not None:
err = _do_named_tz(args)
else:
err = _do_lon_tz(args)
except Exception as exc:
Expand Down
34 changes: 32 additions & 2 deletions src/python/timezone_solar/timezone_solar.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,43 @@ def _tz_params_latitude(cls, tz_params):
# no effects on results from latitude between 80° north & south
return None

# generate time zone parameters from given time zone name
@classmethod
def _tz_name2params(cls, tzname: str) -> dict:
match = re.fullmatch(r"^Lon(\d{3})([EW])$", tzname, flags=re.IGNORECASE)
if match:
is_west = match.group(2) == "W"
longitude = int(match.group(1)) * (-1 if is_west else 1)
if abs(int(longitude)) > 180:
raise ValueError(f"longitude {longitude} is out of bounds ±180")
use_lon_tz = True
return {"longitude": longitude, "use_lon_tz": use_lon_tz}
match = re.fullmatch(r"^(East|West)(\d{2})$", tzname, flags=re.IGNORECASE)
if match:
is_west = match.group(1) == "West"
hour_num = int(match.group(2))
if hour_num > 12:
raise ValueError(f"time zone hour {hour_num} is out of bounds ±12")
longitude = hour_num * 15 * (-1 if is_west else 1)
if abs(int(longitude)) > 180:
raise ValueError(f"longitude {longitude} is out of bounds ±180")
use_lon_tz = False
return {"longitude": longitude, "use_lon_tz": use_lon_tz}
raise ValueError(f"{tzname} is not a valid solar/natural time zone name")

# get timezone parameters (name and minutes offset) - called by __new__()
@classmethod
def _tz_params(cls, tz_params) -> dict:
def _tz_params(cls, tz_params: dict) -> dict:

# rewrite parameters based on time zone if a tzname was provided
if "tzname" in tz_params and tz_params["tzname"] is not None:
tz_params = cls._tz_name2params(tz_params["tzname"])

# longitude is required
if "longitude" not in tz_params:
raise ValueError("_tz_params: longitude parameter missing")

# set time zone from longitude and latitude
# set time zone from longitude and latitude, if latitude was provided
if "latitude" in tz_params and tz_params["latitude"] is not None:
lat_params = cls._tz_params_latitude(tz_params)
if lat_params is not None:
Expand Down

0 comments on commit 609e25e

Please sign in to comment.