Skip to content

Calling astimezone() on a deserialized DatetimeWithNanoseconds raises AttributeError #543

@jrobbins

Description

@jrobbins

Environment details

  • Programming language: Python
  • OS: Linux
  • Language runtime version: 3.12.9
  • Package version: 1.26.1

Steps to reproduce

  1. Retrieve a model object stored in Google NDB that has a ndb.DateTimeProperty field.
  2. Call astimezone(pytz.timezone('US/Pacific')) on that field value.

Apparently the _nanoseconds slot is not filled in, which raises the AttributeError exception. This may be because our data was stored in Firestore using a previous version of NDB and this library.

Here is a partial traceback from our code:

ERROR:main:Exception on /api/v0/features/32373/gates [GET]
Traceback (most recent call last):
.
.
.
  File "/usr/local/google/home/jrobbins/testgh/chromium-dashboard/api/converters.py", line 676, in gate_value_to_json_dict
    slo_initial_response_took = slo.weekdays_between(
                                ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/google/home/jrobbins/testgh/chromium-dashboard/internals/slo.py", line 41, in weekdays_between
    d_ptz = start.astimezone(PACIFIC_TZ)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/google/home/jrobbins/testgh/chromium-dashboard/cs-env/lib/python3.12/site-packages/pytz/tzinfo.py", line 201, in fromutc
    dt = dt.replace(tzinfo=None)
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/google/home/jrobbins/testgh/chromium-dashboard/cs-env/lib/python3.12/site-packages/proto/datetime_helpers.py", line 108, in replace
    prev_nanos = self.nanosecond
                 ^^^^^^^^^^^^^^^
  File "/usr/local/google/home/jrobbins/testgh/chromium-dashboard/cs-env/lib/python3.12/site-packages/proto/datetime_helpers.py", line 133, in nanosecond
    return self._nanosecond or self.microsecond * 1000
           ^^^^^^^^^^^^^^^^
AttributeError: 'DatetimeWithNanoseconds' object has no attribute '_nanosecond'. Did you mean: 'nanosecond'?

We are temporarily using the following work-around to create a regular python datetime object
start = datetime.datetime.combine(start.date(), start.time(), start.tzinfo)

And, setting start._nanoseconds = 0 also works around the error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: p2Moderately-important priority. Fix may not be included in next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions