Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ String manipulation nodes:

Date and time manipulation nodes:

- **DateTime creation/conversion**: TimeNow, TimeToUnix, UnixToTime
- **DateTime creation/conversion**: TimeNow, TimeNowUTC, TimeToUnix, UnixToTime
- **String formatting/parsing**: TimeFormat, TimeParse
- **Time calculations**: TimeDelta, TimeAddDelta, TimeSubtractDelta, TimeDifference
- **Component extraction**: TimeExtract (year, month, day, hour, etc.)
Expand Down
34 changes: 34 additions & 0 deletions src/basic_data_handling/time_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,38 @@ def get_now(self, trigger=None) -> tuple[datetime.datetime]:
return (datetime.datetime.now(),)


class TimeNowUTC(ComfyNodeABC):
"""
Returns the current time and date as a DATETIME object, in the UTC timezone.
Note: Output changes for every run, providing a fresh timestamp each time.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"trigger": (IO.ANY, {"description": "Optional input to trigger execution"})
}
}

RETURN_TYPES = (IO.DATETIME,)
RETURN_NAMES = ("now",)
CATEGORY = "Basic/time"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "get_now_utc"

@classmethod
def IS_CHANGED(s, **kwargs):
# Always return a changing value to indicate the output changes every run
return time.time()

def get_now_utc(self, trigger=None) -> tuple[datetime.datetime]:
"""
Retrieves the current system time in the UTC timezone.
The optional trigger input can be used to trigger execution.
"""
return (datetime.datetime.now(datetime.UTC),)


class TimeToUnix(ComfyNodeABC):
"""
Converts a DATETIME object to a Unix timestamp (a float representing seconds since the epoch).
Expand Down Expand Up @@ -287,6 +319,7 @@ def extract(self, datetime: datetime.datetime) -> tuple[int, int, int, int, int,

NODE_CLASS_MAPPINGS = {
"Basic data handling: TimeNow": TimeNow,
"Basic data handling: TimeNowUTC": TimeNowUTC,
"Basic data handling: TimeToUnix": TimeToUnix,
"Basic data handling: UnixToTime": UnixToTime,
"Basic data handling: TimeFormat": TimeFormat,
Expand All @@ -300,6 +333,7 @@ def extract(self, datetime: datetime.datetime) -> tuple[int, int, int, int, int,

NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: TimeNow": "Time Now",
"Basic data handling: TimeNowUTC": "Time Now (UTC)",
"Basic data handling: TimeToUnix": "Time to Unix Timestamp",
"Basic data handling: UnixToTime": "Unix Timestamp to Time",
"Basic data handling: TimeFormat": "Format Time String",
Expand Down
14 changes: 14 additions & 0 deletions tests/test_time_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from datetime import datetime, timedelta
from src.basic_data_handling.time_nodes import (
TimeNow,
TimeNowUTC,
TimeToUnix,
UnixToTime,
TimeFormat,
Expand All @@ -27,6 +28,19 @@ def test_time_now():
assert len(result_with_trigger) == 1
assert isinstance(result_with_trigger[0], datetime)

def test_time_now_utc():
node = TimeNowUTC()
result = node.get_now_utc()
assert isinstance(result, tuple)
assert len(result) == 1
assert isinstance(result[0], datetime)

# Test with trigger parameter
result_with_trigger = node.get_now_utc(trigger="any value")
assert isinstance(result_with_trigger, tuple)
assert len(result_with_trigger) == 1
assert isinstance(result_with_trigger[0], datetime)

def test_time_to_unix():
node = TimeToUnix()
test_datetime = datetime(2023, 1, 1, 12, 0, 0)
Expand Down