How to Convert a Utc Datetime to a Local Datetime Using Only Standard Library

How to convert a UTC datetime to a local datetime using only standard library?

I think I figured it out: computes number of seconds since epoch, then converts to a local timzeone using time.localtime, and then converts the time struct back into a datetime...

EPOCH_DATETIME = datetime.datetime(1970,1,1)
SECONDS_PER_DAY = 24*60*60

def utc_to_local_datetime( utc_datetime ):
delta = utc_datetime - EPOCH_DATETIME
utc_epoch = SECONDS_PER_DAY * delta.days + delta.seconds
time_struct = time.localtime( utc_epoch )
dt_args = time_struct[:6] + (delta.microseconds,)
return datetime.datetime( *dt_args )

It applies the summer/winter DST correctly:

>>> utc_to_local_datetime( datetime.datetime(2010, 6, 6, 17, 29, 7, 730000) )
datetime.datetime(2010, 6, 6, 19, 29, 7, 730000)
>>> utc_to_local_datetime( datetime.datetime(2010, 12, 6, 17, 29, 7, 730000) )
datetime.datetime(2010, 12, 6, 18, 29, 7, 730000)

Convert UTC datetime string to local datetime

If you don't want to provide your own tzinfo objects, check out the python-dateutil library. It provides tzinfo implementations on top of a zoneinfo (Olson) database such that you can refer to time zone rules by a somewhat canonical name.

from datetime import datetime
from dateutil import tz

# METHOD 1: Hardcode zones:
from_zone = tz.gettz('UTC')
to_zone = tz.gettz('America/New_York')

# METHOD 2: Auto-detect zones:
from_zone = tz.tzutc()
to_zone = tz.tzlocal()

# utc = datetime.utcnow()
utc = datetime.strptime('2011-01-21 02:37:21', '%Y-%m-%d %H:%M:%S')

# Tell the datetime object that it's in UTC time zone since
# datetime objects are 'naive' by default
utc = utc.replace(tzinfo=from_zone)

# Convert time zone
central = utc.astimezone(to_zone)

Edit Expanded example to show strptime usage

Edit 2 Fixed API usage to show better entry point method

Edit 3 Included auto-detect methods for timezones (Yarin)

How to convert local time string to UTC?

Thanks @rofly, the full conversion from string to string is as follows:

time.strftime("%Y-%m-%d %H:%M:%S", 
time.gmtime(time.mktime(time.strptime("2008-09-17 14:04:00",
"%Y-%m-%d %H:%M:%S"))))

My summary of the time/calendar functions:

time.strptime
string --> tuple (no timezone applied, so matches string)

time.mktime
local time tuple --> seconds since epoch (always local time)

time.gmtime
seconds since epoch --> tuple in UTC

and

calendar.timegm
tuple in UTC --> seconds since epoch

time.localtime
seconds since epoch --> tuple in local timezone

Converting UTC DateTime to local DateTime

If you know the DateTime contains a UTC value, you can use the following:

DateTime iKnowThisIsUtc = whatever;
DateTime runtimeKnowsThisIsUtc = DateTime.SpecifyKind(
iKnowThisIsUtc,
DateTimeKind.Utc);
DateTime localVersion = runtimeKnowsThisIsUtc.ToLocalTime();

For example, in my current application, I create timestamps in my database with SQL's utcnow, but when I read them into my C# application the Kind proeprty is always Unknown. I created a wrapper function to read the timestamp, deliberately set its Kind to Utc, and then convert it to local time - essentially as above.

Note that DateTime.ToLocalTime() only doesn't affect the value if one (or both) of the following holds:

  • The DateTime's Kind property is DateTimeKind.Local
  • Your local timezone is such that "no change" is the correct conversion

I think we can assume the second point isn't true. Thus it seems that iKnowThisIsUtc's Kind property is set to Local already. You need to figure out why whatever is supplying you with these DateTimes thinks they are local.

Convert UTC time to local time while using the local year/month/day and specifying the hours/minutes JAVA

tl;dr

ZonedDateTime.now().with( LocalTime.of( 9 , 0 ) )

The LocalTime object, when passed to the with method, acts as a TemporalAdjuster, to move to a different date-time value. That value is delivered in a fresh new object rather than altering the original, as immutable objects.

The line of code above depends implicitly on the JVM’s current default time zone. Better to specify explicitly.

Details

By the way, do not mix legacy date-time classes with java.time classes. Avoid the legacy classes entirely. So this:

ZoneId localZoneId = ZoneId.of(TimeZone.getDefault().getID());

…should be:

ZoneId localZoneId = ZoneId.systemDefault() ;

Also, “local” in java.time means “not zoned”, or the zone/offset is unknown or unspecified. So your variable name localZoneId is confusing. Should be something like this:

ZoneId zoneId = ZoneId.systemDefault() ;

You said:

I want to grab the current year, month, day from the local machine

Determining the current date requires a time zone. For any given moment, the date varies around the globe by time zone.

ZoneId z = ZoneId.systemDefault() ;
LocalDate today = LocalDate.now( z ) ;

You said:

but still keep the hour/minutes at 09:00

A ZonedDateTime represents a date and a time-of-day, in the context of a time zone. You can specify each of those three parts in the factory method ZonedDateTime.of.

LocalTime lt = LocalTime.of( 9 , 0 ) ;
ZonedDateTime zdt = ZonedDateTime.of( today , lt , z ) ; // Pass date, time, zone.


Related Topics



Leave a reply



Submit