将 UTC 日期时间字符串转换为本地日期时间

2024-12-17 08:30:00
admin
原创
158
摘要:问题描述:我从未需要将时间转换为 UTC 或从 UTC 转换为 UTC。最近有人要求我的应用能够识别时区,但我一直都不知道该怎么做。关于将本地时间转换为 UTC 的信息很多,我觉得这相当基础(也许我做错了),但我找不到任何关于如何轻松地将 UTC 时间转换为最终用户时区的信息。简而言之,android 应用程...

问题描述:

我从未需要将时间转换为 UTC 或从 UTC 转换为 UTC。最近有人要求我的应用能够识别时区,但我一直都不知道该怎么做。关于将本地时间转换为 UTC 的信息很多,我觉得这相当基础(也许我做错了),但我找不到任何关于如何轻松地将 UTC 时间转换为最终用户时区的信息。

简而言之,android 应用程序向我发送(appengine 应用程序)数据,并且该数据中包含一个时间戳。为了将该时间戳存储为 utc 时间,我使用:

datetime.utcfromtimestamp(timestamp)

这似乎有效。当我的应用存储数据时,它会被存储为提前 5 小时的数据(我的是 EST -5)

数据存储在 appengine 的 BigTable 中,检索时会以字符串形式显示,如下所示:

"2011-01-21 02:37:21"

如何将此字符串转换为用户正确时区的 DateTime?

另外,建议如何存储用户的时区信息?(您通常如何存储 tz 信息,即:“-5:00”或“EST”等等?)我确信我的第一个问题的答案可能包含一个回答第二个问题的参数。


解决方案 1:

如果您不想提供自己的tzinfo对象,请查看python-dateutil库。它tzinfo在zoneinfo (Olson) 数据库之上提供实现,以便您可以通过一个有点规范的名称来引用时区规则。

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()

# Since datetime.utcnow() is deprecated since version 3.12 use datetime.now()
# utc = datetime.now()  
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)

编辑扩展示例以显示strptime用法

编辑 2修复 API 使用问题,以显示更好的入口点方法

编辑 3包含时区自动检测方法(Yarin)

解决方案 2:

这是一种不依赖任何外部库的弹性方法:

from datetime import datetime
import time

def datetime_from_utc_to_local(utc_datetime):
    now_timestamp = time.time()
    offset = datetime.fromtimestamp(now_timestamp) - datetime.utcfromtimestamp(now_timestamp)
    return utc_datetime + offset

这避免了 DelboyJay 示例中的时间问题。以及 Erik van Oosten 修正案中较小的时间问题。

有趣的是,上面计算的时区偏移量可能与以下看似等效的表达式不同,这可能是由于夏令时规则的变化:

offset = datetime.fromtimestamp(0) - datetime.utcfromtimestamp(0) # NO!

更新:此代码片段的缺点是使用当前时间的 UTC 偏移量,这可能与输入日期时间的 UTC 偏移量不同。请参阅此答案的评论以了解另一种解决方案。

为了解决不同的时间问题,请从传入的时间中获取纪元时间。这是我所做的:

def utc2local(utc):
    epoch = time.mktime(utc.timetuple())
    offset = datetime.fromtimestamp(epoch) - datetime.utcfromtimestamp(epoch)
    return utc + offset

解决方案 3:

已更新为最新的 Python 3 支持(请参阅旧答案的编辑历史):

从 Python 3.9 开始,内置zoneinfo库中提供了时区信息:

该模块提供了具体的时区实现,以支持PEP 615zoneinfo中最初指定的 IANA 时区数据库。默认情况下,如果可用,则使用系统的时区数据;如果没有可用的系统时区数据,则库将回退到使用 PyPI 上可用的第一方包。zoneinfo`tzdata`

请参阅zoneinfo.available_timezones()时区名称列表。

这是一个简单的例子:

# "pip install -U tzdata" for latest zone support required on some OSes
import datetime as dt
import zoneinfo as zi

GMT = zi.ZoneInfo('GMT')
ExT = zi.ZoneInfo('US/Eastern')

print(dt.datetime.now(tz=GMT).strftime('%m/%d/%Y %H:%M:%S %Z'))
print(dt.datetime.now(tz=ExT).strftime('%m/%d/%Y %H:%M:%S %Z'))

t = dt.datetime.strptime('2011-01-21 02:37:21','%Y-%m-%d %H:%M:%S')
t = t.replace(tzinfo=GMT)
print(t)
print(t.astimezone(ExT))

# Preferred way now instead of utcfromtimestamp().
# See https://docs.python.org/3/library/datetime.html#datetime.datetime.utcfromtimestamp.
d = dt.datetime.fromtimestamp(1714365725, tz=dt.UTC)  # time zone-aware

# Formatting in different zones
print(d.strftime('%Y-%m-%d %I:%M:%S %p %Z'))
print(d.astimezone(ExT).strftime('%Y-%m-%d %I:%M:%S %p %Z'))
print(d.astimezone(zi.ZoneInfo('US/Pacific')).strftime('%Y-%m-%d %I:%M:%S %p %Z'))

输出:

04/29/2024 04:46:19 GMT
04/29/2024 00:46:19 EDT
2011-01-21 02:37:21+00:00
2011-01-20 21:37:21-05:00
2024-04-29 04:42:05 AM UTC
2024-04-29 12:42:05 AM EDT
2024-04-28 09:42:05 PM PDT

解决方案 4:

如果您想要获得正确的结果,即使对于对应于模糊的本地时间(例如,在 DST 转换期间)的时间和/或本地 utc 偏移量在您本地时区的不同时间不同,请使用pytz时区:

#!/usr/bin/env python
from datetime import datetime
import pytz    # $ pip install pytz
import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone() # get pytz tzinfo
utc_time = datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
local_time = utc_time.replace(tzinfo=pytz.utc).astimezone(local_timezone)

解决方案 5:

如果您不想使用除此之外的任何其他模块,这个答案应该会有所帮助datetime

datetime.utcfromtimestamp(timestamp)返回一个简单datetime对象(不是感知对象)。感知对象可以感知时区,简单对象则不能。如果您想在时区之间进行转换(例如在 UTC 和本地时间之间),则需要一个感知对象。

如果您不是首先实例化日期的人,但仍然可以datetime在 UTC 时间中创建一个简单对象,则可能需要尝试使用此 Python 3.x 代码进行转换:

import datetime

d=datetime.datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S") #Get your naive datetime object
d=d.replace(tzinfo=datetime.timezone.utc) #Convert it to an aware datetime object in UTC time.
d=d.astimezone() #Convert it to your local timezone (still aware)
print(d.strftime("%d %b %Y (%I:%M:%S:%f %p) %Z")) #Print it with a directive of choice

请注意不要误以为,如果您的时区当前为 MDT,则夏令时不适用于上述代码,因为它会打印 MST。您会注意到,如果您将月份更改为 8 月,它会打印 MDT。

获取感知datetime对象的另一种简单方法(在 Python 3.x 中也是如此)是在创建时指定时区。以下是使用 UTC 的示例:

import datetime, sys

aware_utc_dt_obj=datetime.datetime.now(datetime.timezone.utc) #create an aware datetime object
dt_obj_local=aware_utc_dt_obj.astimezone() #convert it to local time

#The following section is just code for a directive I made that I liked.
if sys.platform=="win32":
    directive="%#d %b %Y (%#I:%M:%S:%f %p) %Z"
else:
    directive="%-d %b %Y (%-I:%M:%S:%f %p) %Z"

print(dt_obj_local.strftime(directive))

如果您使用 Python 2.x,您可能必须进行子类化datetime.tzinfo并使用它来帮助您创建一个感知datetime对象,因为datetime.timezone在 Python 2.x 中不存在。

解决方案 6:

如果使用Django,可以使用该timezone.localtime方法:

from django.utils import timezone
date 
# datetime.datetime(2014, 8, 1, 20, 15, 0, 513000, tzinfo=<UTC>)

timezone.localtime(date)
# datetime.datetime(2014, 8, 1, 16, 15, 0, 513000, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)

解决方案 7:

以下内容在美国西部的云环境中对我有用:

import datetime
import pytz

#set the timezone
tzInfo = pytz.timezone('America/Los_Angeles')
dt = datetime.datetime.now(tz=tzInfo)
print(dt)

解决方案 8:

将franksands的答案整合成一种方便的方法。

import calendar
import datetime

def to_local_datetime(utc_dt):
    """
    convert from utc datetime to a locally aware datetime according to the host timezone

    :param utc_dt: utc datetime
    :return: local timezone datetime
    """
    return datetime.datetime.fromtimestamp(calendar.timegm(utc_dt.timetuple()))

解决方案 9:

您可以使用箭头

from datetime import datetime
import arrow

now = datetime.utcnow()

print(arrow.get(now).to('local').format())
# '2018-04-04 15:59:24+02:00'

你可以输入arrow.get()任何东西。时间戳、iso 字符串等

解决方案 10:

从这里的答案中,您可以使用时间模块将 utc 转换为计算机中设置的本地时间:

utc_time = time.strptime("2018-12-13T10:32:00.000", "%Y-%m-%dT%H:%M:%S.%f")
utc_seconds = calendar.timegm(utc_time)
local_time = time.localtime(utc_seconds)

解决方案 11:

这对我有用:

from django.utils import timezone
from datetime import timedelta,datetime

ist_time = timezone.now() + timedelta(hours=5,minutes=30)

#second method

ist_time = datetime.now() + timedelta(hours=5,minutes=30)

解决方案 12:

您可以使用calendar.timegm将时间转换为自 Unix 纪元以来的秒数,然后time.localtime转换回来:

import calendar
import time

time_tuple = time.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
t = calendar.timegm(time_tuple)

print time.ctime(t)

给予Fri Jan 21 05:37:21 2011(因为我处于 UTC+03:00 时区)。

解决方案 13:

import datetime

def utc_str_to_local_str(utc_str: str, utc_format: str, local_format: str):
    """
    :param utc_str: UTC time string
    :param utc_format: format of UTC time string
    :param local_format: format of local time string
    :return: local time string
    """
    temp1 = datetime.datetime.strptime(utc_str, utc_format)
    temp2 = temp1.replace(tzinfo=datetime.timezone.utc)
    local_time = temp2.astimezone()
    return local_time.strftime(local_format)

utc_tz_example_str = '2018-10-17T00:00:00.111Z'
utc_fmt = '%Y-%m-%dT%H:%M:%S.%fZ'
local_fmt = '%Y-%m-%dT%H:%M:%S+08:00'

# call my function here
local_tz_str = utc_str_to_local_str(utc_tz_example_str, utc_fmt, local_fmt)
print(local_tz_str)   # 2018-10-17T08:00:00+08:00

当我输入utc_tz_example_str= 2018-10-17T00:00:00.111Z,(UTC +00:00)

时,我将得到local_tz_str= 2018-10-17T08:00:00+08:00 (我的目标时区+08:00)

参数utc_format是你具体确定的格式utc_tz_example_str

参数local_fmt是最终想要的格式。

就我而言,我想要的格式是%Y-%m-%dT%H:%M:%S+08:00(+08:00 时区)。您应该构建所需的格式。

解决方案 14:

我传统上将其推迟到前端 - 从后端发送时间作为时间戳或 UTC 中的其他日期时间格式,然后让客户端找出时区偏移量并在适当的时区中呈现该数据。

对于 web 应用程序来说,这在 javascript 中很容易实现——您可以使用内置方法轻松找出浏览器的时区偏移量,然后正确地从后端呈现数据。

解决方案 15:

  1. 首先确保您的计算机/服务器具有正确的时区,有时您可能会看到正确的时间,但使用错误的时区,因为系统根据互联网调整时间。

这是我的工作代码,允许时区自动检测并支持 DST 时区:

from datetime import datetime, timedelta

def datetime_from_utc_to_local(utc_string ):  #"2023-09-30T17:49:06.000Z"
    # Extract the offset from the input string, assuming it's always in the format "-HHMM"
    local_offset_str = datetime.now().astimezone().isoformat(timespec="seconds")[-6:]

    # Convert the offset string to an integer representing hours an minutes
    offset_hours = int(local_offset_str[:3])
    offset_minutes = int(local_offset_str[4:])

    # Create a datetime object from the input string, excluding the "Z" character
    utc_datetime = datetime.fromisoformat(utc_string[:-1]) 

    # Apply the offset to convert the GMT datetime to the local time
    local_datetime = utc_datetime + timedelta(hours=offset_hours, minutes=offset_minutes)
    
    return local_datetime

解决方案 16:

这是一个快速而粗糙的版本,它使用本地系统设置来计算时差。注意:如果您需要转换为当前系统未运行的时区,则此方法将不起作用。我已经使用 BST 时区下的英国设置对此进行了测试

from datetime import datetime
def ConvertP4DateTimeToLocal(timestampValue):
   assert isinstance(timestampValue, int)

   # get the UTC time from the timestamp integer value.
   d = datetime.utcfromtimestamp( timestampValue )

   # calculate time difference from utcnow and the local system time reported by OS
   offset = datetime.now() - datetime.utcnow()

   # Add offset to UTC time and return it
   return d + offset
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2560  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1552  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。其中,技术评审与决策评审是IPD流程中至关重要的环节,它们既有明显的区别,又存在紧密的协同关系。深入理解这两者的区别与协同,对于企业有效实施IPD流程,提升产品开发效率与质量具有重要意义...
IPD管理流程   1  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、ClickUp、Freshdesk、GanttPRO、Planview、Smartsheet、Asana、Nifty、HubPlanner、Teamwork。在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目按时交付的关键工具。然而...
项目管理系统   2  
  建设工程项目质量关乎社会公众的生命财产安全,也影响着企业的声誉和可持续发展。高质量的建设工程不仅能为使用者提供舒适、安全的环境,还能提升城市形象,推动经济的健康发展。在实际的项目操作中,诸多因素会对工程质量产生影响,从规划设计到施工建设,再到后期的验收维护,每一个环节都至关重要。因此,探寻并运用有效的方法来提升建设工程...
工程项目管理制度   3  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用