How to create tzinfo when I have UTC offset?

If you can, take a look at the excellent dateutil package instead of implementing this yourself.

Specifically, tzoffset. It's a fixed offset tzinfo instance initialized with offset, given in seconds, which is what you're looking for.

Update

Here's an example. Be sure to run pip install python-dateutil first.

from datetime import datetime
from dateutil import tz

# First create the tzinfo object
tzlocal = tz.tzoffset('IST', 19800)

# Now add it to a naive datetime
local = naive.replace(tzinfo=tzlocal)

# Or convert another timezone to it
utcnow = datetime.utcnow().replace(tzinfo=tz.tzutc())
now = utcnow.astimezone(tzlocal)

I looked up the name IST from here. The name can really be anything. Just be careful if you deviate, since if you use code that relies on the name, it could lead to bugs later on.

By the way, if you have the timezone name upfront, and your operating system supports it, you can use gettz instead:

# Replace the above with this
tzlocal = tz.gettz('IST')

With Python 3.2 or higher, you can do this using the builtin datetime library:

import datetime
datetime.timezone(-datetime.timedelta(hours=5, minutes=30)

To solve your specific problem, you could use regex:

sign, hours, minutes = re.match('([+\-]?)(\d{2})(\d{2})', '+0530').groups()
sign = -1 if sign == '-' else 1
hours, minutes = int(hours), int(minute)

tzinfo = datetime.timezone(sign * datetime.timedelta(hours=hours, minutes=minutes))
datetime.datetime(2013, 2, 3, 9, 45, tzinfo=tzinfo)

Python Standard Library (8.1.6) says that :

  • tzinfo is an abstract base class
  • the datetime module does not supply any concrete subclasses of tzinfo
  • you need to derive a concrete subclass, and (at least) supply implementations of the standard tzinfo methods needed by the datetime methods you use
  • a concrete subclass of tzinfo may need to implement the following methods ... If in doubt, simply implement all of them
    • tzinfo.utcoffset(self, dt) : return offset of local time from UTC, in minutes east of UTC
    • tzinfo.dst(self, dt) : return the daylight saving time (DST) adjustment, in minutes east of UTC, or None if DST information isn’t known
    • tzinfo.tzname(self, dt) : return the time zone name corresponding to the datetime object dt, as a string

All that means that you will have to provide your own implementation for the tzinfo. For example :

class UTC0530(datetime.tzinfo):
    """tzinfo derived concrete class named "+0530" with offset of 19800"""
    # can be configured here
    _offset = datetime.timedelta(seconds = 19800)
    _dst = datetime.timedelta(0)
    _name = "+0530"
    def utcoffset(self, dt):
        return self.__class__._offset
    def dst(self, dt):
        return self.__class__._dst
    def tzname(self, dt):
        return self.__class__._name

Usage :

tz = UTC0530()
d = datetime.datetime.now(tz)
d.isoformat()

output :

2015-01-27T20:19:41.257000+05:30

You have to implement subclass of datetime.tzinfo class. General guide is described here, where you also can find excellent examples of custom tzinfo implementations.

Here is example (given that there is no daylight saving time) :

from datetime import tzinfo, timedelta, datetime
from pytz import UTC


class MyUTCOffsetTimezone (tzinfo):

    def __init__(self, offset=19800, name=None):
        self.offset = timedelta(seconds=offset)
        self.name = name or self.__class__.__name__

    def utcoffset(self, dt):
        return self.offset

    def tzname(self, dt):
        return self.name

    def dst(self, dt):
        return timedelta(0)


now = datetime.now(tz=UTC)
print now
# -> 2015-01-28 10:46:42.256841+00:00
print now.astimezone(MyUTCOffsetTimezone())
# -> 2015-01-28 16:16:42.256841+05:30
print datetime.now(MyUTCOffsetTimezone())
# -> 2015-01-28 16:16:42.256915+05:30