protobuf icon indicating copy to clipboard operation
protobuf copied to clipboard

Python: Timestamp.ToDatetime should have an ability to get a timezone-aware datetime object

Open tswast opened this issue 5 years ago • 8 comments

What language does this apply to?

If it's about generated code change, what programming language?

Python. Well-known-types Timestamp.

Describe the problem you are trying to solve.

There are many times where it makes a difference between having a timezone-aware and timezone-naive datetime object in Python. For example, you cannot compare equality between a timezone-naive and a timezone-aware datetime object.

Describe the solution you'd like

I'd like for Timestamp.ToDatetime to return a timezone-aware datetime with a UTC timezone, but understand this would be a breaking change. Instead, it would probably be preferable to

  • Add a Timestamp.ToUTCDatetime method to create a timezone-aware datetime.

The answer at https://stackoverflow.com/a/21952077/101923 shows how to create a timezone-aware datetime. Probably the dependency on pytz should be optional.

https://github.com/googleapis/google-cloud-python/blob/a6d849912eea6b9260ccb64ffb317d8265b354a6/core/google/cloud/_helpers.py#L630-L633

Shows how to make the dependency on pytz optional.

Describe alternatives you've considered

  • Timestamp.ToDatetime to take a tzinfo object (though ideally it should always be UTC).

    Problematic, because it requires first converting to timezone-aware UTC, then converting to the request timezone for correct behavior.

  • Timestamp.ToDatetime to take a boolean option to return a timezone-aware datetime.

    Problematic, because there isn't really precedent for this in the datetime module that I could find. Also, boolean flags like this are always a bit less clear than having a second method that clearly shows the desired result.

tswast avatar Mar 18 '19 17:03 tswast

From the link, I believe you can convert the returned datetime to timezone-aware datetime by:

import pytz dt = message.ToDatetime() aware_utc_dt = dt.replace(tzinfo=pytz.utc)

anandolee avatar Mar 18 '19 19:03 anandolee

From the link, I believe you can convert the returned datetime to timezone-aware datetime by:

Yes, I'm now doing that in our code samples. This feature request is to add a method to do that so that it's one less thing to look up how to do.

Maybe what I should do instead is update the "generated code docs" to clarify that ToDatetime returns a naive datetime object?

tswast avatar Mar 18 '19 21:03 tswast

I think it is reasonable to assume if a project needs a timezone-aware datetime, they should know how the convert naive datetime and timezone-aware datetime, also how to convert local time with other timezone.

Update the generated code docs is slow (for small issue, the priority is low), but you can create a PR and update the API document: https://github.com/protocolbuffers/protobuf/blob/bf32b36ab8aa9e56c031e00c0553db640d3627d4/python/google/protobuf/internal/well_known_types.py#L222

anandolee avatar Mar 18 '19 23:03 anandolee

From the link, I believe you can convert the returned datetime to timezone-aware datetime by:

import pytz dt = message.ToDatetime() aware_utc_dt = dt.replace(tzinfo=pytz.utc)

I getting error in message.ToDatetime():

details = "Exception calling application: ToDateTime"

XDavidT avatar Nov 13 '19 08:11 XDavidT

While this is extra steps, would this also be a reasonable workaround in client code?

datetime.fromtimestamp(model.starting_from.seconds, timezone.utc)

I mean, I guess you'd have to copy the nanos/_NANOS portion everywhere for that level of precision or write a utility somewhere - so that's annoying.

The Python3 docs recommend against utcfromtimestamp in any case (https://docs.python.org/3/library/datetime.html#datetime.datetime.utcnow), but changing from a naive to aware datetime is a breaking change.

It would be great to have that native API out of the Python library - is there any planning on this?

sureshjoshi avatar Dec 14 '20 18:12 sureshjoshi

Hello everyone, if I use FromDatetime, first to get Timestamp, and then if I convert this timestamp into datetime with ToDatetime, ending datetime and the original datetime are not same, weirdly I get 1970-01-01 00:00:00+00:00 for all of the conversion for ToDatetime. How can I get same datetimes?

Yalchin403 avatar Jul 20 '22 20:07 Yalchin403

Looks like this has been updated since 1 Feb here

The new signature is:

def ToDatetime(self, tzinfo=None):
    """Converts Timestamp to a datetime.
    Args:
      tzinfo: A datetime.tzinfo subclass; defaults to None.
    Returns:
      If tzinfo is None, returns a timezone-naive UTC datetime (with no timezone
      information, i.e. not aware that it's UTC).
      Otherwise, returns a timezone-aware datetime in the input timezone.
    """

officialgupta avatar Aug 25 '22 13:08 officialgupta

We triage inactive PRs and issues in order to make it easier to find active work. If this issue should remain active or becomes active again, please add a comment.

This issue is labeled inactive because the last activity was over 90 days ago.

github-actions[bot] avatar May 02 '24 10:05 github-actions[bot]

We triage inactive PRs and issues in order to make it easier to find active work. If this issue should remain active or becomes active again, please reopen it.

This issue was closed and archived because there has been no new activity in the 14 days since the inactive label was added.

github-actions[bot] avatar May 18 '24 10:05 github-actions[bot]