diff --git a/aws_lambda_powertools/utilities/data_classes/appsync/resolver_utils.py b/aws_lambda_powertools/utilities/data_classes/appsync/resolver_utils.py index 848a24619d4..b4b49888e24 100644 --- a/aws_lambda_powertools/utilities/data_classes/appsync/resolver_utils.py +++ b/aws_lambda_powertools/utilities/data_classes/appsync/resolver_utils.py @@ -1,35 +1,9 @@ -import datetime -import time -import uuid from typing import Any, Dict from aws_lambda_powertools.utilities.data_classes import AppSyncResolverEvent from aws_lambda_powertools.utilities.typing import LambdaContext -def make_id(): - return str(uuid.uuid4()) - - -def aws_date(): - now = datetime.datetime.utcnow().date() - return now.strftime("%Y-%m-%d") - - -def aws_time(): - now = datetime.datetime.utcnow().time() - return now.strftime("%H:%M:%S") - - -def aws_datetime(): - now = datetime.datetime.utcnow() - return now.strftime("%Y-%m-%dT%H:%M:%SZ") - - -def aws_timestamp(): - return int(time.time()) - - class AppSyncResolver: def __init__(self): self._resolvers: dict = {} diff --git a/aws_lambda_powertools/utilities/data_classes/appsync/scalar_types_utils.py b/aws_lambda_powertools/utilities/data_classes/appsync/scalar_types_utils.py new file mode 100644 index 00000000000..71bfbe7046a --- /dev/null +++ b/aws_lambda_powertools/utilities/data_classes/appsync/scalar_types_utils.py @@ -0,0 +1,89 @@ +import datetime +import time +import uuid + + +def _formatted_time(now: datetime.date, fmt: str, timezone_offset: int) -> str: + """String formatted time with optional timezone offset + + Parameters + ---------- + now : datetime.date + Current datetime with zero timezone offset + fmt : str + Data format before adding timezone offset + timezone_offset : int + Timezone offset in hours, defaults to 0 + Returns + ------- + str + Returns string formatted time with optional timezone offset + """ + if timezone_offset == 0: + return now.strftime(fmt + "Z") + + now = now + datetime.timedelta(hours=timezone_offset) + fmt += "+" if timezone_offset > 0 else "-" + fmt += str(abs(timezone_offset)).zfill(2) + fmt += ":00:00" + + return now.strftime(fmt) + + +def make_id() -> str: + """ID - A unique identifier for an object. This scalar is serialized like a String but isn't meant to be + human-readable.""" + return str(uuid.uuid4()) + + +def aws_date(timezone_offset: int = 0) -> str: + """AWSDate - An extended ISO 8601 date string in the format YYYY-MM-DD. + + Parameters + ---------- + timezone_offset : int + Timezone offset, defaults to 0 + + Returns + ------- + str + Returns current time as AWSDate scalar string with optional timezone offset + """ + return _formatted_time(datetime.datetime.utcnow(), "%Y-%m-%d", timezone_offset) + + +def aws_time(timezone_offset: int = 0) -> str: + """AWSTime - An extended ISO 8601 time string in the format hh:mm:ss.sss. + + Parameters + ---------- + timezone_offset : int + Timezone offset, defaults to 0 + + Returns + ------- + str + Returns current time as AWSTime scalar string with optional timezone offset + """ + return _formatted_time(datetime.datetime.utcnow(), "%H:%M:%S", timezone_offset) + + +def aws_datetime(timezone_offset: int = 0) -> str: + """AWSDateTime - An extended ISO 8601 date and time string in the format YYYY-MM-DDThh:mm:ss.sssZ. + + Parameters + ---------- + timezone_offset : int + Timezone offset, defaults to 0 + + Returns + ------- + str + Returns current time as AWSDateTime scalar string with optional timezone offset + """ + return _formatted_time(datetime.datetime.utcnow(), "%Y-%m-%dT%H:%M:%S", timezone_offset) + + +def aws_timestamp() -> int: + """AWSTimestamp - An integer value representing the number of seconds before or after 1970-01-01-T00:00Z.""" + return int(time.time()) diff --git a/tests/functional/appsync/test_appsync_resolver_utils.py b/tests/functional/appsync/test_appsync_resolver_utils.py index b3ec85c7205..a1388a1fb5c 100644 --- a/tests/functional/appsync/test_appsync_resolver_utils.py +++ b/tests/functional/appsync/test_appsync_resolver_utils.py @@ -7,8 +7,9 @@ import pytest from aws_lambda_powertools.utilities.data_classes import AppSyncResolverEvent -from aws_lambda_powertools.utilities.data_classes.appsync.resolver_utils import ( - AppSyncResolver, +from aws_lambda_powertools.utilities.data_classes.appsync.resolver_utils import AppSyncResolver +from aws_lambda_powertools.utilities.data_classes.appsync.scalar_types_utils import ( + _formatted_time, aws_date, aws_datetime, aws_time, @@ -196,19 +197,19 @@ def test_make_id(): assert len(uuid) == 36 -def test_aws_date(): +def test_aws_date_utc(): date_str = aws_date() assert isinstance(date_str, str) - assert datetime.datetime.strptime(date_str, "%Y-%m-%d") + assert datetime.datetime.strptime(date_str, "%Y-%m-%dZ") -def test_aws_time(): +def test_aws_time_utc(): time_str = aws_time() assert isinstance(time_str, str) - assert datetime.datetime.strptime(time_str, "%H:%M:%S") + assert datetime.datetime.strptime(time_str, "%H:%M:%SZ") -def test_aws_datetime(): +def test_aws_datetime_utc(): datetime_str = aws_datetime() assert isinstance(datetime_str, str) assert datetime.datetime.strptime(datetime_str, "%Y-%m-%dT%H:%M:%SZ") @@ -217,3 +218,17 @@ def test_aws_datetime(): def test_aws_timestamp(): timestamp = aws_timestamp() assert isinstance(timestamp, int) + + +def test_format_time_positive(): + now = datetime.datetime(2022, 1, 22) + datetime_str = _formatted_time(now, "%Y-%m-%d", 8) + assert isinstance(datetime_str, str) + assert datetime_str == "2022-01-22+08:00:00" + + +def test_format_time_negative(): + now = datetime.datetime(2022, 1, 22, 14, 22, 33) + datetime_str = _formatted_time(now, "%H:%M:%S", -12) + assert isinstance(datetime_str, str) + assert datetime_str == "02:22:33-12:00:00"