Source code for utdf2gmns.util_lib.pkg_utils

# -*- coding:utf-8 -*-
##############################################################
# Created Date: Wednesday, November 16th 2022
# Contact Info: luoxiangyong01@gmail.com
# Author/Copyright: Mr. Xiangyong Luo
##############################################################

import math
from math import sin, cos, sqrt, atan2, radians
from datetime import datetime
import pyufunc as pf


[docs] def calculate_point2point_distance_in_km(point1: list, point2: list) -> float: """ point1 and point2: a tuple of (longitude, latitude) """ # TDD: Test-Driven Development # assert isinstance(point1, list), "point1 should be a list" # assert isinstance(point2, list), "point2 should be a list" # approximate radius of earth in km R = 6373.0 lon1 = radians(point1[0]) lat1 = radians(point1[1]) lon2 = radians(point2[0]) lat2 = radians(point2[1]) lon_diff = lon2 - lon1 lat_diff = lat2 - lat1 a = sin(lat_diff / 2)**2 + cos(lat1) * cos(lat2) * sin(lon_diff / 2)**2 c = 2 * atan2(sqrt(a), sqrt(1 - a)) return R * c
def point_on_line(x1, y1, x2, y2, distance): """ Calculate the (x, y) coordinates on the line from (x1, y1) to (x2, y2) at a given distance from the starting point (x1, y1). Parameters: x1, y1 : float Coordinates of the starting point. x2, y2 : float Coordinates of the ending point. distance : float The distance from the starting point at which to find the point. Returns: (x, y) : tuple of floats The coordinates of the point along the line. """ # Calculate the difference in coordinates dx = x2 - x1 dy = y2 - y1 # Calculate the total length of the line segment line_length = math.sqrt(dx**2 + dy**2) # If the points are identical, return the starting point if line_length == 0: return x1, y1 # Determine the ratio of the given distance to the total length ratio = distance / line_length # Calculate the new coordinates using the ratio x = x1 + ratio * dx y = y1 + ratio * dy return x, y
[docs] def time_unit_converter(value: float, from_unit: str, to_unit: str, verbose: bool = True) -> float: """ Convert a time value between seconds, minutes, hours, days, years Args: value (float): The numerical value to convert. from_unit (str): The unit of the input value. to_unit (str): The desired output unit. Example: >>> from pyufunc import time_unit_converter >>> time_unit_converter(1, "hours", "minutes") 60.0 Returns: float: The converted value in the target unit. Raises: ValueError: If an invalid unit is provided. """ # Define aliases to standardize unit names. unit_aliases = { "s": "seconds", "sec": "seconds", "secs": "seconds", "second": "seconds", "seconds": "seconds", "m": "minutes", "min": "minutes", "mins": "minutes", "minute": "minutes", "minutes": "minutes", "h": "hours", "hr": "hours", "hrs": "hours", "hour": "hours", "hours": "hours", "d": "days", "day": "days", "days": "days", "y": "years", "yr": "years", "yrs": "years", "year": "years", "years": "years", "season": "season", "seasons": "season", "quarter": "quarter", "quarters": "quarter", "lunar year": "lunar year", "lunar years": "lunar year" } # Conversion factors in seconds. conversion_factors = { "seconds": 1, "minutes": 60, # 60 seconds "hours": 3600, # 60 minutes * 60 seconds "days": 86400, # 24 hours * 3600 seconds "years": 31536000, # 365 days * 86400 seconds } # Normalize the provided unit strings. from_unit_norm = unit_aliases.get(from_unit.lower().strip()) to_unit_norm = unit_aliases.get(to_unit.lower().strip()) if from_unit_norm is None or to_unit_norm is None: raise ValueError( "Invalid unit provided. Allowed units: seconds, minutes, hours, days, years, season, quarter, lunar year.") # Convert the input value to seconds. value_in_seconds = value * conversion_factors[from_unit_norm] # Convert from seconds to the target unit. result = value_in_seconds / conversion_factors[to_unit_norm] if verbose: print( f" :{value} {from_unit_norm} is approximately {result} {to_unit_norm}") return result
[docs] def time_str_to_seconds(time_str: str, to_unit: str = "seconds", verbose: bool = True) -> int: """Convert a time string to seconds Args: time_str (str): A time string, e.g., "12:00AM", "9:00am", "3:00pm" to_unit (str): The desired output unit. e.g. "seconds", "minutes", "hours", "days" verbose (bool): Whether to print the conversion result. Defaults to True. Example: >>> from pyufunc import time_str_to_seconds >>> time_str_to_seconds("12:00AM") 0 >>> time_str_to_seconds("9:00am") 34200.0 >>> time_str_to_seconds("3:30pm") 55800.0 >>> time_str_to_seconds("3:30pm", to_unit="minutes") 930.0 Returns: int: The time in the target unit. """ time_str = pf.str_strip(time_str).lower() fmt = [ "%I:%M", # 12-hour, no AM/PM "%I:%M:%S", # 12-hour with seconds "%I:%M%p", # 12-hour with AM/PM "%I:%M %p", # 12-hour with AM/PM "%H:%M", # 24-hour "%H:%M:%S" # 24-hour with seconds ] dt = None for each_fmt in fmt: try: dt = datetime.strptime(time_str, each_fmt) break except ValueError: continue if dt is None: raise ValueError(f" :Invalid time string: {time_str}") total_seconds = dt.hour * 3600 + dt.minute * 60 + dt.second unit_aliases = { "s": "seconds", "sec": "seconds", "secs": "seconds", "second": "seconds", "seconds": "seconds", "m": "minutes", "min": "minutes", "mins": "minutes", "minute": "minutes", "minutes": "minutes", "h": "hours", "hr": "hours", "hrs": "hours", "hour": "hours", "hours": "hours", "d": "days", "day": "days", "days": "days", "y": "years", "yr": "years", "yrs": "years", "year": "years", "years": "years", } # Conversion factors in seconds. conversion_factors = { "seconds": 1, "minutes": 60, # 60 seconds "hours": 3600, # 60 minutes * 60 seconds "days": 86400, # 24 hours * 3600 seconds "years": 31536000, # 365 days * 86400 seconds } # Convert from seconds to the target unit. to_unit_norm = unit_aliases.get(to_unit.lower().strip()) result = total_seconds / conversion_factors[to_unit_norm] if verbose: print( f" :{time_str} is approximately {result} {to_unit_norm}") return result