TimeComponents

Takes a date or time input and get time components in a specific time zone. Returns a dictionary with the following components. - year - year_4_digit - month - month_3_letter - month_full_name - month_2_digit - day - day_2_digit - day_of_week (Sun:0, Sat:6) - day_of_week_3_letter - day_of_week_full_name - day_of_year - day_of_year_3_digit - hour - hour_12_clock - hour_2_digit_24_clock - hour_2_digit_12_clock - hour_of_day - minute - minute_2_digit - minute_of_day - second - second_2_digit - second_of_day - millisecond - period_12_clock - time_zone_hhmm - time_zone_offset - time_zone_abbreviations - unix_epoch_time - iso_8601 - y-m-d - yyyy-mm-dd - h:m:s - H:m:s - hh:mm:ss - HH:mm:ss.

python · Filters And Transformers

Source

import re
from datetime import UTC, timezone, tzinfo

import dateparser
import demistomock as demisto  # noqa: F401
import pytz
from CommonServerPython import *  # noqa: F401


def timezone_abbreviations(utc_offset: Optional[timedelta]) -> set[str]:
    tznames = set()
    if utc_offset is not None:
        now = datetime.now(pytz.utc)
        for tz in map(pytz.timezone, pytz.all_timezones_set):
            if (d := now.astimezone(tz)).utcoffset() == utc_offset and (tzname := d.tzname()) and tzname[0:1] not in ("+", "-"):
                tznames.add(tzname)
    return tznames


def detect_time_zone(value: Any) -> tzinfo:
    if isinstance(value, int):
        return timezone(timedelta(minutes=value))

    if isinstance(value, str):
        value = value.strip()
        if value == "Z":
            return timezone(timedelta(hours=0))
        elif m := re.fullmatch("([+-])([0-9]{1,2})(:?([0-9]{2}))?", value):
            # +H, +HMM, +HHMM, +H:MM, +HH:MM
            offset = ((int(m[2]) * 60) + int(m[4] or 0)) * (-1 if m[1] == "-" else 1)
            return timezone(timedelta(minutes=offset))
        elif m := re.match(r"(^|\s)(UTC|GMT)([+-])([0-9]{1,2})(:?([0-9]{2}))?($|\s)", value):
            # Includes: UTC+H, UTC+HMM, UTC+HHMM, UTC+H:MM, UTC+HH:MM
            offset = ((int(m[4]) * 60) + int(m[6] or 0)) * (-1 if m[3] == "-" else 1)
            return timezone(timedelta(minutes=offset))
        else:
            # Try to parse as zone info
            try:
                return pytz.timezone(value)
            except Exception:
                pass

            # Try to parse as time string
            try:
                d = dateparser.parse(value)
                if d is not None and d.tzinfo is not None:
                    return d.tzinfo
            except Exception:
                pass

    raise DemistoException(f"Unable to extract time zone - {value}")


def parse_date_time_value(value: Any) -> datetime:
    """Parse a date time value

    :param value: The date or time to parse
    :return: aware datetime object
    """
    if value in [None, ""]:
        return datetime.now(UTC)

    if isinstance(value, int):
        # Parse as time stamp
        try:
            # Considered the value as seconds > milliseconds > microseconds when it's too large (> uint max).
            # (Currently later than 2106-02-07 06:28:15)
            while value > 4294967295:
                value /= 1000

            return datetime.fromtimestamp(value).astimezone(UTC)
        except Exception as err:
            raise DemistoException(f"Error with input date / time - {err}")

    if isinstance(value, str):
        value = value.strip()
        try:
            # Parse as time stamp
            return parse_date_time_value(int(value))
        except (TypeError, ValueError):
            pass

    try:
        date_time = dateparser.parse(value)
        assert date_time is not None, f"could not parse {value}"

        if date_time.tzinfo is not None:
            return date_time

        date_time = dateparser.parse(value, settings={"TIMEZONE": "UTC", "RETURN_AS_TIMEZONE_AWARE": True})
        assert date_time is not None, f"could not parse {value}"
        return date_time
    except Exception as err:
        raise DemistoException(f"Error with input date / time - {err}")


def main():
    try:
        args = demisto.args()
        date_time = parse_date_time_value(args.get("value"))
        if time_zone := args.get("time_zone"):
            date_time = date_time.astimezone(detect_time_zone(time_zone))

        time_components = {
            "year": date_time.year,
            "year_4_digit": date_time.strftime("%Y"),
            "month": date_time.month,
            "month_3_letter": date_time.strftime("%b"),
            "month_full_name": date_time.strftime("%B"),
            "month_2_digit": date_time.strftime("%m"),
            "day": date_time.day,
            "day_2_digit": date_time.strftime("%d"),
            "day_of_week": int(date_time.strftime("%w")),
            "day_of_week_3_letter": date_time.strftime("%a"),
            "day_of_week_full_name": date_time.strftime("%A"),
            "day_of_year": int(date_time.strftime("%j")),
            "day_of_year_3_digit": date_time.strftime("%j"),
            "hour": date_time.hour,
            "hour_12_clock": (date_time.hour % 12) or 12,
            "hour_2_digit_24_clock": date_time.strftime("%H"),
            "hour_2_digit_12_clock": date_time.strftime("%I"),
            "hour_of_day": date_time.hour + (date_time.minute / 60) + (date_time.second / 60 / 60),
            "minute": date_time.minute,
            "minute_2_digit": date_time.strftime("%M"),
            "minute_of_day": (date_time.hour * 24) + date_time.minute + (date_time.second / 60),
            "second": date_time.second,
            "second_2_digit": date_time.strftime("%S"),
            "second_of_day": (date_time.hour * 24 * 60) + (date_time.minute * 60) + date_time.second,
            "millisecond": int(date_time.microsecond / 1000),
            "period_12_clock": date_time.strftime("%p"),
            "time_zone_hhmm": date_time.strftime("%z"),
            "time_zone_offset": (date_time.utcoffset() or timedelta(hours=0)).total_seconds() / 60,
            "time_zone_abbreviations": sorted(timezone_abbreviations(date_time.utcoffset())),
            "unix_epoch_time": int(date_time.timestamp()),
            "iso_8601": date_time.isoformat(),
            "y-m-d": f"{date_time.year}-{date_time.month}-{date_time.day}",
            "yyyy-mm-dd": f"{date_time.strftime('%Y-%m-%d')}",
            "h:m:s": f"{date_time.hour}:{date_time.minute}:{date_time.second}",
            "H:m:s": f"{(date_time.hour % 12) or 12}:{date_time.minute}:{date_time.second}",
            "hh:mm:ss": f"{date_time.strftime('%I:%M:%S')}",
            "HH:mm:ss": f"{date_time.strftime('%H:%M:%S')}",
        }

        if key := args.get("key"):
            if (component := time_components.get(key)) is None:
                raise DemistoException(f"No key is found in the time components - {key}")
            return_results(component)
        else:
            return_results(time_components)
    except Exception as err:
        # Don't return an error by return_error() as this is transformer.
        raise DemistoException(str(err))


if __name__ in ("__main__", "builtin", "builtins"):
    main()

README

Takes a date or time input and get time components in a specific time zone.
Returns a dictionary with the following components.

  • year
  • year_4_digit
  • month
  • month_3_letter
  • month_full_name
  • month_2_digit
  • day
  • day_2_digit
  • day_of_week (Sun:0, Sat:6)
  • day_of_week_3_letter
  • day_of_week_full_name
  • day_of_year
  • day_of_year_3_digit
  • hour
  • hour_12_clock
  • hour_2_digit_24_clock
  • hour_2_digit_12_clock
  • hour_of_day
  • minute
  • minute_2_digit
  • minute_of_day
  • second
  • second_2_digit
  • second_of_day
  • millisecond
  • period_12_clock
  • time_zone_hhmm
  • time_zone_offset
  • time_zone_abbreviations
  • unix_epoch_time
  • iso_8601
  • y-m-d
  • yyyy-mm-dd
  • h:m:s
  • H:m:s
  • hh:mm:ss
  • HH:mm:ss

Script Data


Name Description
Script Type python3
Tags transformer, date
Cortex XSOAR Version 6.5.0

Inputs


Argument Name Description
value Input date or time in a format that is supported by the dateparser.parse() function as outlined here- https://dateparser.readthedocs.io/en/latest/#popular-formats. For example: ‘2020-01-01’ or ‘1999/02/03 12:01:59’. (Default is the current time). Assume given time is in UTC if time zone is not detected.
time_zone The time zone (e.g. -0400, +09:00) or time string to extract a time zone
key The name of a key to choose which time component to return

Outputs


There are no outputs for this script.

Examples


Get all the time components from the time taken

Parameters

Argument Name Value
value 2022-01-23 01:23:45 +00:00
time_zone  
key  

Output

{
  "year": 2022,
  "year_4_digit": "2022",
  "month": 1,
  "month_3_letter": "Jan",
  "month_full_name": "January",
  "month_2_digit": "01",
  "day": 23,
  "day_2_digit": "23",
  "day_of_week": 0,
  "day_of_week_3_letter": "Sun",
  "day_of_week_full_name": "Sunday",
  "day_of_year": 23,
  "day_of_year_3_digit": "023",
  "hour": 1,
  "hour_12_clock": 1,
  "hour_2_digit_24_clock": "01",
  "hour_2_digit_12_clock": "01",
  "hour_of_day": 1.3958333333333333,
  "minute": 23,
  "minute_2_digit": "23",
  "minute_of_day": 47.75,
  "second": 45,
  "second_2_digit": "45",
  "second_of_day": 2865,
  "millisecond": 0,
  "period_12_clock": "AM",
  "time_zone_hhmm": "+0000",
  "time_zone_offset": 0.0,
  "time_zone_abbreviations": ["GMT", "UTC", "WET"],
  "unix_epoch_time": 1642901025,
  "iso_8601": "2022-01-23T01:23:45+00:00",
  "y-m-d": "2022-1-23",
  "yyyy-mm-dd": "2022-01-23",
  "h:m:s": "1:23:45",
  "H:m:s": "1:23:45",
  "hh:mm:ss": "01:23:45",
  "HH:mm:ss": "01:23:45"
}

Get all the time components in a specific time zone

Parameters

Argument Name Value
value 2022-01-23 01:23:45 +00:00
time_zone +09:00
key  

Output

{
  "year": 2022,
  "year_4_digit": "2022",
  "month": 1,
  "month_3_letter": "Jan",
  "month_full_name": "January",
  "month_2_digit": "01",
  "day": 23,
  "day_2_digit": "23",
  "day_of_week": 0,
  "day_of_week_3_letter": "Sun",
  "day_of_week_full_name": "Sunday",
  "day_of_year": 23,
  "day_of_year_3_digit": "023",
  "hour": 10,
  "hour_12_clock": 10,
  "hour_2_digit_24_clock": "10",
  "hour_2_digit_12_clock": "10",
  "hour_of_day": 10.395833333333332,
  "minute": 23,
  "minute_2_digit": "23",
  "minute_of_day": 263.75,
  "second": 45,
  "second_2_digit": "45",
  "second_of_day": 15825,
  "millisecond": 0,
  "period_12_clock": "AM",
  "time_zone_hhmm": "+0900",
  "time_zone_offset": 540.0,
  "time_zone_abbreviations": ["JST", "KST", "WIT"],
  "unix_epoch_time": 1642901025,
  "iso_8601": "2022-01-23T10:23:45+09:00",
  "y-m-d": "2022-1-23",
  "yyyy-mm-dd": "2022-01-23",
  "h:m:s": "10:23:45",
  "H:m:s": "10:23:45",
  "hh:mm:ss": "10:23:45",
  "HH:mm:ss": "10:23:45"
}

Get all the time components from the unix timestamp

Parameters

Argument Name Value
value 1642868625
time_zone  
key  

Output

{
  "year": 2022,
  "year_4_digit": "2022",
  "month": 1,
  "month_3_letter": "Jan",
  "month_full_name": "January",
  "month_2_digit": "01",
  "day": 22,
  "day_2_digit": "22",
  "day_of_week": 6,
  "day_of_week_3_letter": "Sat",
  "day_of_week_full_name": "Saturday",
  "day_of_year": 22,
  "day_of_year_3_digit": "022",
  "hour": 16,
  "hour_12_clock": 4,
  "hour_2_digit_24_clock": "16",
  "hour_2_digit_12_clock": "04",
  "hour_of_day": 16.395833333333332,
  "minute": 23,
  "minute_2_digit": "23",
  "minute_of_day": 407.75,
  "second": 45,
  "second_2_digit": "45",
  "second_of_day": 24465,
  "millisecond": 0,
  "period_12_clock": "PM",
  "time_zone_hhmm": "+0000",
  "time_zone_offset": 0.0,
  "time_zone_abbreviations": ["GMT", "UTC", "WET"],
  "unix_epoch_time": 1642868625,
  "iso_8601": "2022-01-22T16:23:45+00:00",
  "y-m-d": "2022-1-22",
  "yyyy-mm-dd": "2022-01-22",
  "h:m:s": "16:23:45",
  "H:m:s": "4:23:45",
  "hh:mm:ss": "04:23:45",
  "HH:mm:ss": "16:23:45"
}

Get a specific time component (day_of_week_full_name)

Parameters

Argument Name Value
value 2022-01-23 01:23:45 +00:00
time_zone  
key day_of_week_full_name

Output

Sunday

Get a time component in a specific time zone given by zone info

Parameters

Argument Name Value
value 2022-01-23 01:23:45 +00:00
time_zone Asia/Tokyo
key iso_8601

Output

2022-01-23T10:23:45+09:00

Get a time component in a time zone which is extracted from the time string given to time_zone

Parameters

Argument Name Value
value 2022-01-23 01:23:45 +00:00
time_zone 2022-01-01 00:00:00 +09:00
key iso_8601

Output

2022-01-23T10:23:45+09:00

Get a current time in a specific time zone

Parameters

Argument Name Value
value now
time_zone +09:00
key iso_8601

Output

2022-09-30T12:34:56+09:00

Tips

Build a custom time format string

You can create a custom time format in combination with the DT transformer on the chain of transformers. For example, now you want to create a RFC 1123 date string such as Thu, 10 Nov 2022 08:01:44 +0200, and have the following results from the TimeComponents.

Table 1

{
    "year": 2022,
    "year_4_digit": "2022",
    "month": 11,
    "month_3_letter": "Nov",
    "month_full_name": "November",
    "month_2_digit": "11",
    "day": 10,
    "day_2_digit": "10",
    "day_of_week": 4,
    "day_of_week_3_letter": "Thu",
    "day_of_week_full_name": "Thursday",
    "day_of_year": 314,
    "day_of_year_3_digit": "314",
    "hour": 8,
    "hour_12_clock": 8,
    "hour_2_digit_24_clock": "08",
    "hour_2_digit_12_clock": "08",
    "hour_of_day": 8.02888888888889,
    "minute": 1,
    "minute_2_digit": "01",
    "minute_of_day": 193.73333333333332,
    "second": 44,
    "second_2_digit": "44",
    "second_of_day": 11624,
    "millisecond": 0,
    "period_12_clock": "AM",
    "time_zone_hhmm": "+0200",
    "time_zone_offset": 120.0,
    "unix_epoch_time": 1668060104,
    "iso_8601": "2022-11-10T08:01:44+02:00",
    "y-m-d": "2022-11-10",
    "yyyy-mm-dd": "2022-11-10",
    "h:m:s": "8:1:44",
    "H:m:s": "8:1:44",
    "hh:mm:ss": "08:01:44",
    "HH:mm:ss": "08:01:44"
}

You can set the following value to the dt parameter of the DT transformer to build the RFC 1123 date string you want.

Parameters to DT

Argument Name Value
value <Table 1>
dt .=val.day_of_week_3_letter + “, “ + val.day + “ “ + val.month_3_letter + “ “ + val.year + “ “ + val[“HH:mm:ss”] + “ “ + val.time_zone_hhmm

Output

Thu, 10 Nov 2022 08:01:44 +0200