{"record":{"id":"b4bdaa1c50c09925","repo":"apache/beam","slug":"dt-not-in-utc-s","errorCode":null,"errorMessage":"dt not in UTC: %s","messagePattern":"dt not in UTC: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/utils/timestamp.py","lineNumber":167,"sourceCode":"\n  @staticmethod\n  def _epoch_datetime_utc() -> datetime.datetime:\n    return datetime.datetime.fromtimestamp(0, pytz.utc)\n\n  @classmethod\n  def from_utc_datetime(cls, dt: datetime.datetime) -> 'Timestamp':\n    \"\"\"Create a ``Timestamp`` instance from a ``datetime.datetime`` object.\n\n    Args:\n      dt: A ``datetime.datetime`` object in UTC (offset-aware).\n    \"\"\"\n    if dt.tzinfo is None:\n      raise ValueError(\n          \"dt has no timezone info \" +\n          \"(https://docs.python.org/3/library/datetime.html\" +\n          \"#aware-and-naive-objects): %s\" % dt)\n    if dt.tzinfo != pytz.utc and dt.tzinfo != datetime.timezone.utc:\n      raise ValueError('dt not in UTC: %s' % dt)\n    duration = dt - cls._epoch_datetime_utc()\n    # Avoid total_seconds(): its float result can be off by a microsecond.\n    return Timestamp(\n        seconds=duration.days * 86400 + duration.seconds,\n        micros=duration.microseconds)\n\n  @classmethod\n  def from_rfc3339(cls, rfc3339: str) -> 'Timestamp':\n    \"\"\"Create a ``Timestamp`` instance from an RFC 3339 compliant string.\n\n    Fractional seconds up to microseconds produce a microsecond-precision\n    Timestamp; a longer fraction (up to nanoseconds) produces a Timestamp\n    whose precision matches the number of fractional digits.\n\n    .. note::\n      All timezones are implicitly converted to UTC.\n\n    Args:","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/utils/timestamp.py#L149-L185","documentation":"from_utc_datetime() accepts only datetimes whose tzinfo is exactly pytz.utc or datetime.timezone.utc; aware datetimes in other timezones (e.g. pytz timezone 'US/Pacific' or a +05:00 fixed offset) raise this ValueError. The API name means 'from a UTC datetime', not 'convert any datetime to UTC'.","triggerScenarios":"Passing datetime(2024,1,1, tzinfo=timezone(timedelta(hours=5))); passing pytz.timezone('UTC').localize(dt) variants whose tzinfo compares unequal to pytz.utc; passing dt.astimezone() results in some non-UTC tz.","commonSituations":"Application timezone-aware datetimes passed directly instead of converted; pytz's localize used with wrong tz; reading aware datetimes from databases in local tz.","solutions":["Convert first: dt.astimezone(pytz.utc) or dt.astimezone(datetime.timezone.utc), then call from_utc_datetime","Use Timestamp.of(dt), which handles any aware datetime via from_utc_datetime after conversion in newer code paths","Store/produce UTC datetimes at the source instead of local ones"],"exampleFix":"// before\nTimestamp.from_utc_datetime(local_dt)\n// after\nTimestamp.from_utc_datetime(local_dt.astimezone(pytz.utc))","handlingStrategy":"type-guard","validationCode":"if dt.tzinfo not in (pytz.utc, datetime.timezone.utc):\n    dt = dt.astimezone(pytz.utc)","typeGuard":"def is_utc(dt: datetime.datetime) -> bool:\n    return dt.tzinfo in (pytz.utc, datetime.timezone.utc)","tryCatchPattern":"try:\n    ts = Timestamp.from_utc_datetime(dt)\nexcept ValueError as e:\n    if 'not in UTC' in str(e):\n        ts = Timestamp.from_utc_datetime(dt.astimezone(pytz.utc))\n    else:\n        raise","preventionTips":["Normalize all datetimes to UTC at system boundaries with astimezone(pytz.utc)","Only pass UTC datetimes to from_utc_datetime; use Timestamp.of for mixed tz","Beware pytz.localize with non-UTC zones produces non-UTC tzinfo"],"tags":["python","value-error","datetime","timezone"],"backgroundTag":"invalid-date-format","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}