MichaelChirico
MichaelChirico

Reputation: 34713

Convert datetime string, timezone to epoch seconds

I have what seems like a simple question but for which I can find no straightforward answer. I would like to write a function that takes two strings as input and gives an integer as output.

In R, the function would be as simple as:

utc_seconds = function(date_string, tz) as.integer(as.POSIXct(date_string, tz = tz))

I am in control of date_string and know the format will always be proper, e.g. 2018-02-11 00:00:00, and I also know that tz will always be in Olson format.

Example input/output:

utc_seconds('2018-02-11 00:00:00', tz = 'Asia/Singapore')
# 1518278400

I've looked at various combinations/permutations of datetime, pytz, time, etc, to no avail. This table looked promising, but ultimately I couldn't figure out how to use it.

I've managed a "hack" as follows, but this feels inane (adding extraneous information to my input string):

from dateutil.parser import parse
from dateutil.tz import gettz
parse("2018-02-01 00:00:00 X", tzinfos={'X': gettz('Asia/Singapore')})
# datetime.datetime(2018, 2, 11, 0, 0, tzinfo=tzfile('/usr/share/zoneinfo/Asia/Singapore'))

But I can't get that to UTC time either.

Upvotes: 1

Views: 1175

Answers (2)

gyx-hh
gyx-hh

Reputation: 1431

you can use datetime timestamp to get the epoch time

from datetime import datetime
import pytz

def utc_seconds(str_dt, timezone):
    timezone = pytz.timezone(timezone)
    dt = datetime.strptime(str_dt, '%Y-%m-%d %H:%M:%S')
    dt_timezone = timezone.localize(dt)

    return int(dt_timezone.timestamp())

utc_seconds('2018-02-11 00:00:00', 'Asia/Singapore')
# 1518278400

Upvotes: 1

MichaelChirico
MichaelChirico

Reputation: 34713

With the nudge from @Udayraj Deshmukh, I've cobbled together the following:

from dateutil.parser import parse
from pytz import timezone, utc
from datetime import datetime
def utc_seconds(input, tz):
    tz = timezone(tz)
    dt = tz.localize(parse(input), is_dst = None)
    return int((dt - datetime(1970, 1, 1, tzinfo = utc)).total_seconds())
utc_seconds('2018-02-11 00:00:00', 'Asia/Singapore')
# 1518278400

I also came up with the following alternative owing to the happy circumstance that my set-up is already tied into a Spark context:

def utc_seconds(input, tz):
  query = "select unix_timestamp(to_utc_timestamp('{dt}', '{tz}'))" \
            .format(dt = input, tz = tz)
  return spark.sql(query).collect()[0][0]

(i.e., kick the can to a friendlier language and collect the result)

Upvotes: 0

Related Questions