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

PySpark如何配置统一时区保证Parquet读取与手动建DataFrame日期一致

问题根因

出现时间偏移的核心原因是Python原生datetime对象默认是不带时区信息的「naive datetime」,Python进程默认使用运行环境的本地时区解析这类时间,Spark读取到这类时间对象后,会自动转换为Spark会话配置的GMT-4时区时间,就出现了1小时的偏移。而你读取Parquet文件时是直接解析Parquet中存储的时间戳,直接按会话时区转换,所以结果符合预期。

解决方法

方法1:创建带明确时区的datetime对象

手动给传入的datetime对象指定GMT-4时区,避免Spark按Python本地时区转换:

import pytz
from decimal import Decimal
import datetime

spark = get_spark()
# 明确指定datetime的时区为GMT-4(pytz中GMT负偏移对应Etc/GMT+正数值)
gmt4_tz = pytz.timezone('Etc/GMT+4')
df_busqueda = spark.createDataFrame(
    data=[
        [Decimal(2273), Decimal(238171), "SO", datetime.strptime('2005-10-25 00:00:00', '%Y-%m-%d %H:%M:%S').replace(tzinfo=gmt4_tz)],
    ],
    schema=StructType(
        [
            StructField('ID_NUM_CLIENTE', DecimalType(), True),
            StructField('NUM_TRAMITE', DecimalType(), True),
            StructField('COD_TIPO_1', StringType(), True),
            StructField('FECHA_TRAMITE', TimestampType(), True),

        ]
    ),
)

方法2:传入时间字符串后用Spark函数转换

不直接传Python datetime对象,先传时间字符串,再用Spark的时区转换逻辑统一处理:

from pyspark.sql.functions import to_timestamp

spark = get_spark()
df_busqueda = spark.createDataFrame(
    data=[
        [Decimal(2273), Decimal(238171), "SO", '2005-10-25 00:00:00'],
    ],
    schema=StructType(
        [
            StructField('ID_NUM_CLIENTE', DecimalType(), True),
            StructField('NUM_TRAMITE', DecimalType(), True),
            StructField('COD_TIPO_1', StringType(), True),
            StructField('FECHA_TRAMITE_STR', StringType(), True),
        ]
    ),
)
# 按会话时区将字符串转换为时间戳
df_busqueda = df_busqueda.withColumn("FECHA_TRAMITE", to_timestamp("FECHA_TRAMITE_STR", "yyyy-MM-dd HH:mm:ss")).drop("FECHA_TRAMITE_STR")

方法3:统一Python进程时区和Spark会话时区

直接修改Python运行环境的时区为GMT-4,所有naive datetime会默认按该时区解析:

import os
import time

# 启动Spark前先修改Python进程时区为GMT-4
os.environ['TZ'] = 'Etc/GMT+4'
time.tzset()

def get_spark():
    spark = SparkSession.builder.getOrCreate()
    spark.conf.set("spark.sql.parquet.enableVectorizedReader", "false")
    spark.conf.set("spark.sql.legacy.parquet.datetimeRebaseModeInRead", "LEGACY")
    spark.conf.set("spark.sql.session.timeZone", "GMT-4")
    return spark

以上三种方法任选一种即可,都能保证手动创建的DataFrame时间和Parquet读取结果完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 05:51:01