How to check if a datetime object is localized with pytz?

PythonDatetimeTimezonePytz

Python Problem Overview


I want to store a datetime object with a localized UTC timezone. The method that stores the datetime object can be given a non-localized datetime (naive) object or an object that already has been localized. How do I determine if localization is needed?

Code with missing if condition:

class MyClass:
  def set_date(self, d):
    # what do i check here?
    # if(d.tzinfo):
      self.date = d.astimezone(pytz.utc)
    # else:
      self.date = pytz.utc.localize(d)

Python Solutions


Solution 1 - Python

> How do I determine if localization is needed?

From datetime docs:

  • a datetime object d is aware iff:

      d.tzinfo is not None and d.tzinfo.utcoffset(d) is not None
    
  • d is naive iff:

      d.tzinfo is None or d.tzinfo.utcoffset(d) is None
    

Though if d is a datetime object representing time in UTC timezone then you could use in both cases:

self.date = d.replace(tzinfo=pytz.utc)

It works regardless d is timezone-aware or naive.

Note: don't use datetime.replace() method with a timezone with a non-fixed utc offset (it is ok to use it with UTC timezone but otherwise you should use tz.localize() method).

Solution 2 - Python

if you want to check if a datetime object 'd' is localized, check the d.tzinfo, if it is None, no localization.

Solution 3 - Python

Here is a function wrapping up the top answer.

def tz_aware(dt):
    return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None

Solution 4 - Python

Here's a more complete function to convert or coerce a timestamp obj to utc. If it reaches the exception this means the timestamp is not localized. Since it's good practice to always work in UTC within the code, this function is very useful at the entry level from persistence.

def convert_or_coerce_timestamp_to_utc(timeobj):
        out = timeobj
        try:
            out = timeobj.astimezone(pytz.utc) # aware object can be in any timezone
        except (ValueError,TypeError) as exc: # naive
            out = timeobj.replace(tzinfo=pytz.utc)
        return out

The small addition from the 'try catch' in the answer by J.F. Sebastian is the additional catch condition, without which not all naive cases will be caught by the function.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionchiborgView Question on Stackoverflow
Solution 1 - PythonjfsView Answer on Stackoverflow
Solution 2 - PythonCédric JulienView Answer on Stackoverflow
Solution 3 - PythonkblstView Answer on Stackoverflow
Solution 4 - PythoneiTan LaViView Answer on Stackoverflow