使用Pandas的(略微)不稳定的时区的Python日期时间的字符串格式

时间:2017-03-26 11:00:16

标签: python pandas datetime

我无法使用Pandas解析数据的时间戳。

我尝试解析的日期时间格式示例如2012-05-02 01:00:00-05:00。在Pandas文档中,我被驱动到相关的Python datetime formatting文档,这些文档建议我应该使用类似于%Y-%m-%d %H:%M:%S%z的格式化字符串。

我使用了格式化字符串,如下所示......

fmts = {"variable_name": `%Y-%m-%d %H:%M:%S%z`}
df = pd.read_sql_query("SELECT * FROM some_table", con=some_engine, parse_dates=fmts)

此解决方案返回了Dataframe但无法解析请求的列。我想这是因为我的数据的时区组件有一个意想不到的冒号!我给出时区的示例为-05:00%z格式字符串为-0500

有关如何处理此事的任何想法?

1 个答案:

答案 0 :(得分:4)

您可以编写一个函数来转换日期字符串格式。然后它可以应用于列以转换为日期时间。此函数可以返回时区aware or naive timestamps

<强>代码:

import datetime as dt
import pytz

def convert_to_datetime(tz=None):
    """ Convert our custom timezone representation to a datetime

    Timestamp looks like: 2012-05-02 01:00:00-05:00

    :param tz: None, returns UTC relative Naive
               True, returns timezone aware timestamp in UTC
               <tz>, returns timezone aware timestamp in given timezone 
    :return: returns a processing function that can be passed to apply()  
    """

    def func(datetime_string):
        time = datetime_string[:19]
        tz_str = datetime_string[19:]

        # parse the timezone offset to minutes and seconds
        tz_offset = int(
            tz_str[0] + str(int(tz_str[1:3]) * 60 + int(tz_str[4:])))

        # return a datetime that is offset
        result = dt.datetime.strptime(time, '%Y-%m-%d %H:%M:%S') - \
                 dt.timedelta(minutes=tz_offset)

        if tz is not None:
            result = result.replace(tzinfo=pytz.UTC)

            if tz is not True:
                result = result.astimezone(tz)
        return result

    return func

测试代码:

df = pd.DataFrame([
    '2012-05-02 01:00:00-05:00',
    '2012-05-02 03:00:00-05:00'],
    columns=['timestamp'])

df['zulu_no_tz'] = df.timestamp.apply(convert_to_datetime())
df['utc_tz'] = df.timestamp.apply(convert_to_datetime(tz=True))
df['local_tz'] = df.timestamp.apply(convert_to_datetime(
    tz=pytz.timezone('US/Central')))
print(df)

测试结果:

                   timestamp          zulu_no_tz                    utc_tz  \
0  2012-05-02 01:00:00-05:00 2012-05-02 06:00:00 2012-05-02 06:00:00+00:00   
1  2012-05-02 03:00:00-05:00 2012-05-02 08:00:00 2012-05-02 08:00:00+00:00   

                   local_tz  
0 2012-05-02 01:00:00-05:00  
1 2012-05-02 03:00:00-05:00

使用dateutil

如果您有权访问dateutil,则可以使用其解析代码。这是上面func的替代品,它可以很好地处理您的日期格式。

import dateutil

def func(datetime_string):
    result = dateutil.parser.parse(datetime_string).astimezone(pytz.UTC)

    if tz is None:
        result = result.replace(tzinfo=None)
    elif tz is not True:
        result = result.astimezone(tz)
    return result

您还可以使用dateutil.parser apply()中的import dateutil df.timestamp.apply(dateutil.parser.parse) 作为:

  echo "<td>" . "<a href='name.php?name_id=" . $row['name_id'] ."'>". $row['name_id'] . "</a>" . "</td>";     

我不是这种风格的忠实粉丝,因为它应用了固定的偏移时区,这意味着它不能识别夏令时。我个人更喜欢夏令时或简称UTC。