about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/openpyxl/utils/datetime.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/openpyxl/utils/datetime.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-4a52a71956a8d46fcb7294ac71734504bb09bcc2.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/openpyxl/utils/datetime.py')
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/utils/datetime.py140
1 files changed, 140 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/utils/datetime.py b/.venv/lib/python3.12/site-packages/openpyxl/utils/datetime.py
new file mode 100644
index 00000000..bf7e5006
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/utils/datetime.py
@@ -0,0 +1,140 @@
+# Copyright (c) 2010-2024 openpyxl
+
+"""Manage Excel date weirdness."""
+
+# Python stdlib imports
+import datetime
+from math import isnan
+import re
+
+
+# constants
+MAC_EPOCH = datetime.datetime(1904, 1, 1)
+WINDOWS_EPOCH = datetime.datetime(1899, 12, 30)
+CALENDAR_WINDOWS_1900 = 2415018.5   # Julian date of WINDOWS_EPOCH
+CALENDAR_MAC_1904 = 2416480.5       # Julian date of MAC_EPOCH
+CALENDAR_WINDOWS_1900 = WINDOWS_EPOCH
+CALENDAR_MAC_1904 = MAC_EPOCH
+SECS_PER_DAY = 86400
+
+ISO_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
+ISO_REGEX = re.compile(r'''
+(?P<date>(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2}))?T?
+(?P<time>(?P<hour>\d{2}):(?P<minute>\d{2})(:(?P<second>\d{2})(?P<microsecond>\.\d{1,3})?)?)?Z?''',
+                                       re.VERBOSE)
+ISO_DURATION = re.compile(r'PT((?P<hours>\d+)H)?((?P<minutes>\d+)M)?((?P<seconds>\d+(\.\d{1,3})?)S)?')
+
+
+def to_ISO8601(dt):
+    """Convert from a datetime to a timestamp string."""
+    if hasattr(dt, "microsecond") and dt.microsecond:
+        return dt.isoformat(timespec="milliseconds")
+    return dt.isoformat()
+
+
+def from_ISO8601(formatted_string):
+    """Convert from a timestamp string to a datetime object. According to
+    18.17.4 in the specification the following ISO 8601 formats are
+    supported.
+
+    Dates B.1.1 and B.2.1
+    Times B.1.2 and B.2.2
+    Datetimes B.1.3 and B.2.3
+
+    There is no concept of timedeltas in the specification, but Excel
+    writes them (in strict OOXML mode), so these are also understood.
+    """
+    if not formatted_string:
+        return None
+
+    match = ISO_REGEX.match(formatted_string)
+    if match and any(match.groups()):
+        parts = match.groupdict(0)
+        for key in ["year", "month", "day", "hour", "minute", "second"]:
+            if parts[key]:
+                parts[key] = int(parts[key])
+
+        if parts["microsecond"]:
+            parts["microsecond"] = int(float(parts['microsecond']) * 1_000_000)
+
+        if not parts["date"]:
+            dt = datetime.time(parts['hour'], parts['minute'], parts['second'], parts["microsecond"])
+        elif not parts["time"]:
+            dt = datetime.date(parts['year'], parts['month'], parts['day'])
+        else:
+            del parts["time"]
+            del parts["date"]
+            dt = datetime.datetime(**parts)
+        return dt
+
+    match = ISO_DURATION.match(formatted_string)
+    if match and any(match.groups()):
+        parts = match.groupdict(0)
+        for key, val in parts.items():
+            if val:
+                parts[key] = float(val)
+        return datetime.timedelta(**parts)
+
+    raise ValueError("Invalid datetime value {}".format(formatted_string))
+
+
+def to_excel(dt, epoch=WINDOWS_EPOCH):
+    """Convert Python datetime to Excel serial"""
+    if isinstance(dt, datetime.time):
+        return time_to_days(dt)
+    if isinstance(dt, datetime.timedelta):
+        return timedelta_to_days(dt)
+    if isnan(dt.year):  # Pandas supports Not a Date
+        return
+
+    if not hasattr(dt, "date"):
+        dt = datetime.datetime.combine(dt, datetime.time())
+
+    # rebase on epoch and adjust for < 1900-03-01
+    days = (dt - epoch).days
+    if 0 < days <= 60 and epoch == WINDOWS_EPOCH:
+        days -= 1
+    return days + time_to_days(dt)
+
+
+def from_excel(value, epoch=WINDOWS_EPOCH, timedelta=False):
+    """Convert Excel serial to Python datetime"""
+    if value is None:
+        return
+
+    if timedelta:
+        td = datetime.timedelta(days=value)
+        if td.microseconds:
+            # round to millisecond precision
+            td = datetime.timedelta(seconds=td.total_seconds() // 1,
+                                    microseconds=round(td.microseconds, -3))
+        return td
+
+    day, fraction = divmod(value, 1)
+    diff = datetime.timedelta(milliseconds=round(fraction * SECS_PER_DAY * 1000))
+    if 0 <= value < 1 and diff.days == 0:
+        return days_to_time(diff)
+    if 0 < value < 60 and epoch == WINDOWS_EPOCH:
+        day += 1
+    return epoch + datetime.timedelta(days=day) + diff
+
+
+def time_to_days(value):
+    """Convert a time value to fractions of day"""
+    return (
+        (value.hour * 3600)
+        + (value.minute * 60)
+        + value.second
+        + value.microsecond / 10**6
+        ) / SECS_PER_DAY
+
+
+def timedelta_to_days(value):
+    """Convert a timedelta value to fractions of a day"""
+    return value.total_seconds() / SECS_PER_DAY
+
+
+def days_to_time(value):
+    mins, seconds = divmod(value.seconds, 60)
+    hours, mins = divmod(mins, 60)
+    return datetime.time(hours, mins, seconds, value.microseconds)