{"record":{"id":"d8e41813721d7da1","repo":"apache/beam","slug":"converting-r-to-datetime-truncates-it-to-microseconds-set","errorCode":null,"errorMessage":"Converting %r to datetime truncates it to microseconds. Set allow_lossy_conversion=True to allow this conversion.","messagePattern":"Converting %r to datetime truncates it to microseconds\\. Set allow_lossy_conversion=True to allow this conversion\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/utils/timestamp.py","lineNumber":319,"sourceCode":"    avoid offset due to default timezone mismatch.\n\n    Args:\n      has_tz: whether the timezone info is attached, default to False.\n      allow_lossy_conversion: must be set to True to convert a timestamp\n        with precision above microseconds, since ``datetime.datetime`` only\n        supports microsecond resolution; the result is truncated (floored)\n        to whole microseconds.\n\n    Returns:\n      a ``datetime.datetime`` object of UTC for this Timestamp.\n\n    Raises:\n      ValueError: if this timestamp has precision above microseconds and\n        allow_lossy_conversion is not True.\n    \"\"\"\n    if self._precision > Timestamp.MICROS_PRECISION:\n      if not allow_lossy_conversion:\n        raise ValueError(\n            'Converting %r to datetime truncates it to microseconds. Set '\n            'allow_lossy_conversion=True to allow this conversion.' % self)\n      micros_of_second = self._subseconds // _POW_10[self._precision -\n                                                     Timestamp.MICROS_PRECISION]\n    else:\n      micros_of_second = self._subseconds * _POW_10[Timestamp.MICROS_PRECISION -\n                                                    self._precision]\n    # We can't easily construct a datetime object from microseconds, so we\n    # create one at the epoch and add an appropriate timedelta interval.\n    epoch = self._epoch_datetime_utc()\n    if not has_tz:\n      epoch = epoch.replace(tzinfo=None)\n    return epoch + datetime.timedelta(\n        seconds=self._seconds, microseconds=micros_of_second)\n\n  def to_rfc3339(self) -> str:\n    \"\"\"Returns an RFC 3339 string for this Timestamp.\"\"\"\n    if self._precision <= Timestamp.MICROS_PRECISION:","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/utils/timestamp.py#L301-L337","documentation":"Timestamp.to_utc_datetime() converts to a Python datetime, which can only hold microsecond resolution. If the Timestamp has nanosecond precision, the conversion truncates digits, so the method raises ValueError unless allow_lossy_conversion=True explicitly permits that truncation.","triggerScenarios":"Calling ts.to_utc_datetime() (directly or via _utc, to_language_type, or to_rfc3339) on a Timestamp with _precision > 6 without allow_lossy_conversion=True.","commonSituations":"Formatting nanosecond timestamps for logging or JSON output via to_rfc3339; converting beam Timestamps to datetime for use with Python datetime APIs after ingesting nanosecond data.","solutions":["Call ts.to_utc_datetime(allow_lossy_conversion=True) to accept truncation to microseconds.","Convert to microsecond precision first with to_precision(6, allow_lossy_conversion=True) for a single explicit truncation point.","Use ts.to_rfc3339() with lossy flag or work with `.nanos` if full precision must be preserved.","Intercept ValueError around to_utc_datetime and implement custom rounding/formatting that keeps nanos."],"exampleFix":"// before\ndt = ts.to_utc_datetime()\n// after\ndt = ts.to_utc_datetime(allow_lossy_conversion=True)","handlingStrategy":"validation","validationCode":"def safe_to_datetime(ts, allow_lossy=False):\n    if ts.precision > 6 and not allow_lossy:\n        raise ValueError('nanosecond precision would be truncated')\n    return ts.to_utc_datetime(allow_lossy_conversion=allow_lossy)","typeGuard":"def fits_in_datetime(ts):\n    return ts.precision <= 6","tryCatchPattern":"try:\n    dt = ts.to_utc_datetime()\nexcept ValueError:\n    dt = ts.to_precision(6, allow_lossy_conversion=True).to_utc_datetime()","preventionTips":["Remember Python datetime only supports microsecond resolution.","Keep nanosecond data in Beam Timestamps; convert to datetime only for display.","Pass allow_lossy_conversion=True deliberately where truncation is acceptable."],"tags":["python","apache-beam","timestamp","datetime","precision-loss"],"backgroundTag":"value-out-of-range","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"}