You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OSM文件特定时间数据读取报错:时区不兼容问题排查

解决OSM数据特定时间读取的时区兼容问题及警告

问题分析

  • 警告原因:函数内部变量名datedelems与函数名重名,造成变量遮蔽;代码检测工具误判date参数未使用(实际在query中通过@date调用),核心问题是命名冲突。
  • 报错原因:从OSM读取的ts字段是带UTC时区的datetime类型(datetime64[ns, UTC]),而传入的日期字符串转换后是无时区的datetime对象,两者无法直接比较。

解决方案

1. 处理变量遮蔽警告

修改函数内部变量名,避免与函数名重复,消除遮蔽警告:

def datedelems(history, date):
    # 将变量名从datedelems改为temp_df,避免与函数名冲突
    temp_df = (history.query("ts <= @date")
              .groupby(['type','id'])['version']
              .max()
              .reset_index())
    return pandas.merge(temp_df, history, on=['type','id','version'])

2. 解决时区不兼容报错

以下两种方案任选其一即可:

方案A:将传入的日期转换为带UTC时区的Timestamp

把查询日期转换成与ts字段时区一致的对象:

# 生成带UTC时区的目标日期
target_date = pandas.Timestamp("2008-02-01", tz='UTC')
oldelem = datedelems(elements, target_date)
oldelem.head()

方案B:移除DataFrame中ts字段的时区信息

如果业务不需要保留时区,可以将ts字段转换为无时区datetime:
在创建elements DataFrame后添加一行代码:

# 移除ts字段的时区信息
elements['ts'] = elements['ts'].dt.tz_localize(None)

之后直接传入字符串日期即可:

oldelem = datedelems(elements, "2008-02-01")
oldelem.head()

完整修正代码示例

整合所有修改后的完整代码:

import osmium
import pandas

class TimelineHandler(osmium.SimpleHandler):
    def __init__(self):
        osmium.SimpleHandler.__init__(self)
        self.elemtimeline = []

    def relation(self, n):
        self.elemtimeline.append(["relation",
                                  n.id,
                                  n.version,
                                  n.visible,
                                  pandas.Timestamp(n.timestamp),
                                  n.uid,
                                  n.changeset,
                                  len(n.tags)])


tlhandler = TimelineHandler()
tlhandler.apply_file('/.../.../.../koeln-regbez-internal.osh.pbf')
colnames = ['type', 'id', 'version', 'visible', 'ts', 'uid', 'chgset', 'ntags']
elements = pandas.DataFrame(tlhandler.elemtimeline, columns=colnames)

# 方案B:移除时区信息(选方案A则注释此行)
elements['ts'] = elements['ts'].dt.tz_localize(None)

elements = elements.sort_values(by=['type', 'id', 'ts'])
print(elements.head())
elements.to_csv("Köln-metropole.csv", date_format='%Y-%m-%d %H:%M:%S')

def updatedelem(data):
    updata = data.groupby(['type', 'id'])['version'].max().reset_index()
    return pandas.merge(updata, data, on=['id', 'version'])


uptodate_elem = updatedelem(elements)
print(uptodate_elem.head())
elements.to_csv("Köln-metropole.csv", date_format='%Y-%m-%d %H:%M:%S')

# 修正后的datedelems函数
def datedelems(history, date):
    temp_df = (history.query("ts <= @date")
              .groupby(['type','id'])['version']
              .max()
              .reset_index())
    return pandas.merge(temp_df, history, on=['type','id','version'])

# 方案A调用(选方案B则注释此段,改用下方方案B调用)
# target_date = pandas.Timestamp("2008-02-01", tz='UTC')
# oldelem = datedelems(elements, target_date)

# 方案B调用
oldelem = datedelems(elements, "2008-02-01")
print(oldelem.head())

内容的提问来源于stack exchange,提问作者Mustermax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 10:10:33