4
\$\begingroup\$

The function below is designed to return a UTC offset string, in the form used widely by timestamps, of the user's current time for when only naive date time objects are available (no time zone information).

I've tested it on two systems, which are in different time zones, and it works perfectly. However I'd like confirmation that it will work on all systems running Python versions >= 2.6. Can anyone see any potential problems?

Note: The function will only ever be used with the user's current time and so present or past dates and times are not an issue.

import time
from datetime import datetime

def get_utc_offset_str():
    """
    Returns a UTC offset string of the current time suitable for use in the
    most widely used timestamps (i.e. ISO 8601, RFC 3339). For example:
    10 hours ahead, 5 hours behind, and time is UTC: +10:00, -05:00, +00:00
    """

    # Calculate the UTC time difference in seconds.

    timestamp = time.time()
    time_now = datetime.fromtimestamp(timestamp)
    time_utc = datetime.utcfromtimestamp(timestamp)
    utc_offset_secs = (time_now - time_utc).total_seconds()

    # Flag variable to hold if the current time is behind UTC.
    is_behind_utc = False

    # If the current time is behind UTC convert the offset
    # seconds to a positive value and set the flag variable.
    if utc_offset_secs < 0:
        is_behind_utc = True
        utc_offset_secs *= -1

    # Build a UTC offset string suitable for use in a timestamp.

    if is_behind_utc:
        pos_neg_prefix = "-"
    else:
        pos_neg_prefix = "+"

    utc_offset = time.gmtime(utc_offset_secs)
    utc_offset_fmt = time.strftime("%H:%M", utc_offset)
    utc_offset_str = pos_neg_prefix + utc_offset_fmt

    return utc_offset_str
\$\endgroup\$
  • 2
    \$\begingroup\$ Times with no time zone specified are often called "floating" times. \$\endgroup\$ – 200_success Jun 1 '16 at 16:29
  • \$\begingroup\$ Thanks. The Python documentation differentiates between objects that 'know' about time zones and those that do not by calling them aware and naive respectively. \$\endgroup\$ – mattst Jun 1 '16 at 16:37
1
\$\begingroup\$

Take advantage of Python operator overloading

is_behind_utc = time_now < time_utc

If the current time is less the the UTC time then we are behind UTC time.

There is no need to use logic concerning seconds.

Longer names > comments

# Flag variable to hold if the current time is behind UTC.
is_behind_utc = False

Let's analyze the comment:

  • Flag variable : this can easily be deduced as it is a boolean
  • to hold if : each variable holds something
  • the current time : valuable information
  • is behind UTC : already present in the variable name

So I could write:

current_time_is_behind_utc = time_now < time_utc

The name incorporates the valuable information in the comment, avoids the unnecessary and the repetition of the same concept.

Use ternary when sensible

if is_behind_utc:
    pos_neg_prefix = "-"
else:
    pos_neg_prefix = "+"

I cringe because such verbosity obscures what is simple:

pos_neg_prefix = '-' if current_time_is_behind_utc else '+'

Simplify avoiding too many variables

utc_offset_fmt = time.strftime("%H:%M", utc_offset)
utc_offset_str = pos_neg_prefix + utc_offset_fmt

return utc_offset_str

Can simply be:

return pos_neg_prefix + time.strftime("%H:%M", utc_offset)

I think that each additional variable is an addition burden and point of failure in the code being another layer of indirection, and tend to avoid too many variables when sensible.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your comments. You said there is no need to use the logic concerning seconds, but it is needed for the all important call to time.gmtime(utc_offset_secs). I've never liked the Python ternary operator, so almost never use it, nothing wrong with the conditional IMO. My reason for posting was to find out if the way I'm getting the UTC offset will work on all systems running Python versions >= 2.6, as clearly stated in my post, you make no mention of this and just give a critique of my code! \$\endgroup\$ – mattst Jun 1 '16 at 21:10
  • 1
    \$\begingroup\$ @mattst It works for me in Ubuntu 14.04 Python 3.4 \$\endgroup\$ – Caridorc Jun 1 '16 at 22:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.