Merge commit '57598e815bd8554291636435905a1986c1b486f4' as 'utils_v2'
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,271 @@
|
||||
"""
|
||||
|
||||
AUTHOR:
|
||||
|
||||
Khushal P Soonderji
|
||||
|
||||
DATE:
|
||||
|
||||
Friday, 21st jun, 2024
|
||||
|
||||
OBJECTIVE:
|
||||
|
||||
To provide an easy way to work with time.
|
||||
|
||||
REFERENCES:
|
||||
|
||||
N/A
|
||||
|
||||
DOWNLOADS:
|
||||
|
||||
N/A
|
||||
|
||||
"""
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** IMPORT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# To make sibling directories accessible for imports:
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# For date and time handling:
|
||||
import pytz
|
||||
from datetime import datetime, timedelta
|
||||
import dateparser
|
||||
|
||||
# To handle date-time objects from a Numpy array and Pandas Dataframe:
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MACROS / ONE-TIME INIT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# Date-Time Formats:
|
||||
DATE_TIME_FORMATS = (
|
||||
"%d/%m/%y",
|
||||
"%d-%b-%y",
|
||||
"%d-%m-%y",
|
||||
"%d.%m.%y",
|
||||
"%d/%m/%Y",
|
||||
"%d-%b-%Y",
|
||||
"%d-%m-%Y",
|
||||
"%d.%m.%Y",
|
||||
"%d/%b",
|
||||
"%d%m%Y",
|
||||
"%Y%m%d",
|
||||
"%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
|
||||
# Useful Timezones:
|
||||
TIMEZONE_UTC = pytz.timezone("UTC")
|
||||
TIMEZONE_IST = pytz.timezone("Asia/Kolkata")
|
||||
TIMEZONE_ET = pytz.timezone("America/New_York")
|
||||
TIMEZONE_CT = pytz.timezone("America/Chicago")
|
||||
TIMEZONE_MT = pytz.timezone("America/Denver")
|
||||
TIMEZONE_PT = pytz.timezone("America/Los_Angeles")
|
||||
TIMEZONE_JST = pytz.timezone("Asia/Tokyo")
|
||||
TIMEZONE_CET = pytz.timezone("Europe/Paris")
|
||||
TIMEZONE_GMT = pytz.timezone("GMT")
|
||||
TIMEZONE_AEST = pytz.timezone("Australia/Sydney")
|
||||
TIMEZONE_NZST = pytz.timezone("Pacific/Auckland")
|
||||
TIMEZONE_CST = pytz.timezone("Asia/Shanghai")
|
||||
TIMEZONE_KST = pytz.timezone("Asia/Seoul")
|
||||
TIMEZONE_MSK = pytz.timezone("Europe/Moscow")
|
||||
TIMEZONE_BRT = pytz.timezone("America/Sao_Paulo")
|
||||
TIMEZONE_GST = pytz.timezone("Asia/Dubai")
|
||||
TIMEZONE_SAST = pytz.timezone("Africa/Johannesburg")
|
||||
TIMEZONE_AST = pytz.timezone("Asia/Riyadh")
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** VARIABLES ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** FUNCTIONS ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
def translate_date_time_string(
|
||||
datetime_string,
|
||||
source_format = None,
|
||||
destination_format = "%Y-%m-%dT%H:%M:%S"
|
||||
):
|
||||
|
||||
"""
|
||||
To convert an input datetime string to a different format.
|
||||
:param datetime_string: The datetime string to translate.
|
||||
:param source_format: The current format of the string. If not provided, dateparser will be used.
|
||||
:param destination_format: The format to convert to.
|
||||
:return: The converted datetime string.
|
||||
"""
|
||||
|
||||
try:
|
||||
if source_format is None: datetime_obj = dateparser.parse(datetime_string)
|
||||
else: datetime_obj = datetime.strptime(datetime_string, source_format)
|
||||
return datetime_obj.strftime(destination_format)
|
||||
except Exception as exception:
|
||||
return None
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def parse_date_time(input_value, timezone = None, date_formats = None):
|
||||
|
||||
"""
|
||||
To take any kind of input and interpret the datetime from it.
|
||||
:param input_value: Either a string or an integer or some form of datetime representation.
|
||||
:param timezone: The timezone to apply to the interpreted datetime. EXISTING TIMEZONE INFO WILL BE OVERWRITTEN.
|
||||
:param date_formats: The string formats to consider when parsing a string input.
|
||||
:return: The parsed datetime or null.
|
||||
"""
|
||||
|
||||
datetime_object = None
|
||||
date_formats = date_formats or DATE_TIME_FORMATS
|
||||
|
||||
# It could either be in seconds or milliseconds from epoch time's base date (January 1, 1970),
|
||||
# or it could be days since Microsoft Excel's base date (December 31, 1899).
|
||||
if isinstance(input_value, (int, float, np.number)) and not np.isnan(input_value):
|
||||
if input_value > 9999999999.0: datetime_object = datetime.fromtimestamp(input_value / 1000.0)
|
||||
if input_value > 999999.0: datetime_object = datetime.fromtimestamp(input_value)
|
||||
else: datetime_object = datetime.fromtimestamp(input_value * 24 * 60 * 60.0) - timedelta(days = 25569)
|
||||
|
||||
# The input can even be a pre-formatted date:
|
||||
if isinstance(input_value, str):
|
||||
datetime_object = dateparser.parse(input_value, date_formats = date_formats)
|
||||
|
||||
# If the type is a datetime object, then return it as it is:
|
||||
if isinstance(input_value, datetime):
|
||||
datetime_object = input_value
|
||||
|
||||
# If the type is the native datetime format of pandas:
|
||||
if isinstance(input_value, pd._libs.tslibs.timestamps.Timestamp):
|
||||
datetime_object = input_value.to_pydatetime()
|
||||
|
||||
# Process the timezone:
|
||||
if datetime_object is not None and timezone is not None:
|
||||
datetime_object = as_if_timezone(datetime_object, timezone)
|
||||
|
||||
# Done here:
|
||||
return datetime_object
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def get_current_date_time(timezone = None, as_string = False):
|
||||
|
||||
"""
|
||||
Returns the current time as a datetime object.
|
||||
:param timezone: The timezone to apply to the returned datetime.
|
||||
:param as_string: Whether, or not, you want the output as a string.
|
||||
:return: The datetime object/string representing the current time.
|
||||
"""
|
||||
|
||||
if timezone is not None and isinstance(timezone, str): timezone = pytz.timezone(timezone)
|
||||
now = datetime.now(timezone)
|
||||
return now.isoformat() if as_string else now
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def get_current_ist_date_time(as_string = False):
|
||||
|
||||
"""
|
||||
Gives out the current time in IST timezone.
|
||||
:param as_string: Whether, or not, you want the output as a string.
|
||||
:return: The datetime object or string representing the current time.
|
||||
"""
|
||||
|
||||
return get_current_date_time(
|
||||
timezone = TIMEZONE_IST,
|
||||
as_string = as_string
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def get_current_utc_date_time(as_string = False):
|
||||
|
||||
"""
|
||||
Gives out the current time in UTC timezone.
|
||||
:param as_string: Whether, or not, you want the output as a string.
|
||||
:return: The datetime object or string representing the current time.
|
||||
"""
|
||||
|
||||
return get_current_date_time(
|
||||
timezone = TIMEZONE_UTC,
|
||||
as_string = as_string
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def as_if_timezone(datetime_object, timezone):
|
||||
|
||||
"""
|
||||
Ignores existing timezone info and applies the intended timezone.
|
||||
The time stays the same, only the timezone marker changes.
|
||||
e.g. for IST to UTC: 2024-08-09 00:00:00+05:30 --> 2024-08-09 00:00:00+00:00
|
||||
HINT: IT PRETENDS "AS IF" THE TIMEZONE WAS THE INPUT TIMEZONE.
|
||||
:param datetime_object: The datetime object on which the timezone needs to be applied.
|
||||
:param timezone: The timezone that needs to be applied.
|
||||
:return: A timezone-aware datetime object.
|
||||
"""
|
||||
|
||||
tz_object = pytz.timezone(timezone) if isinstance(timezone, str) else timezone
|
||||
return tz_object.localize(datetime_object.replace(tzinfo = None))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def to_timezone(datetime_object, timezone):
|
||||
|
||||
"""
|
||||
Converts from one timezone to another. The time is adjusted by computing the difference between the two timezones.
|
||||
NOTE: THIS FUNCTION ASSUMES THE INPUT WAS IN UTC IF THE INPUT WAS TIMEZONE-NAIVE.
|
||||
e.g. for IST to UTC: 2024-08-09 00:00:00+05:30 --> 2024-08-08 18:30:00+00:00
|
||||
:param datetime_object: The datetime object on which the timezone needs to be applied.
|
||||
:param timezone: The timezone that needs to be applied.
|
||||
:return: A timezone-aware datetime object.
|
||||
"""
|
||||
|
||||
if isinstance(timezone, str): timezone = pytz.timezone(timezone)
|
||||
if datetime_object.tzinfo is None: return datetime_object.replace(tzinfo = TIMEZONE_UTC)
|
||||
return datetime_object.astimezone(timezone)
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MAIN PROGRAM ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
pass
|
||||
Reference in New Issue
Block a user