从 NetCDF 文件转换时间戳(Seconds sins 1.1.1904)

transform timestamp (Seconds sins 1.1.1904) from NetCDF file

即使有好几篇关于NetCDF文件和时间戳转换的帖子,我今天也画空了。

我 读入一个NetCDF数据集(版本3),调用变量信息后:

# Load required Python packages
import netCDF4 as nc
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
import pandas as pd

#read in a NetCDF data set
ds = nc.Dataset(fn)

# call time variable information
print(ds['time'])

我得到的答案是:

<class 'netCDF4._netCDF4.Variable'>
float64 time(time)
    units: seconds since 1904-01-01 00:00:00.000 00:00
    long_name: time UTC
    axis: T
unlimited dimensions: time
current shape = (5760,)
filling on, default _FillValue of 9.969209968386869e+36 used

现在我想将自 1.1.1904 时间戳以来的秒数转换为 DD.MM.YYYY HH:MM:SS.sss 格式。 (顺便说一句:为什么在时间戳之后包含第二个 00:00 信息?)

(1) 我试过:

t = ds['time'][:]
dtime = []
dtime = (pd.to_datetime(t, format='%d.%m.%Y %H:%M:%S.micros') - datetime(1904, 1, 1)).total_seconds()

我得到了错误: pandas_libs\tslibs\strptime.pyx 在 pandas._libs.tslibs.strptime.array_strptime() 时间数据“3730320000”与格式“%d.%m.%Y %H:%M:%S”不匹配(匹配)

(2) 我试过:

d = datetime.strptime("01-01-1904", "%m-%d-%Y")
dt = d + timedelta(seconds=(t))

我明白了 TypeError:timedelta seconds 组件不支持的类型:MaskedArray

(3) 我试过了

d = datetime.strptime("%m-%d-%Y", "01-01-1904")
dt = d + timedelta(seconds=(ds['time']))

我得到了答案: timedelta 秒组件不支持的类型:netCDF4._netCDF4.Variable

有没有人比我现在更清楚地了解解决方案?

谢谢, 斯瓦瓦

NetCDF4 python 库有一个方法:num2date()
https://unidata.github.io/netcdf4-python/#num2date。不需要 datetime 模块。
NetCDF4 变量包含描述变量的元数据属性,如打印输出所示:

print(ds['time']) #特别是时间变量units属性。

# t contains just the numeric values of the time in `seconds since 1904-01-01 00:00:00.000 00:00`

t = ds['time'][:]
dtime = []
# t_var is the NetCDF4 variable which has the `units` attribute.
t_var = ds.['time']
#dtime = (pd.to_datetime(t, format='%d.%m.%Y %H:%M:%S.micros') - datetime(1904, 1, 1)).total_seconds()
dtime = NetCDF4.num2date(t, t_var.units)

上面应该给你 dtime 列表中的所有时间作为日期时间对象。

print(dtime[0].isoformat())
print(dtime[-1].isoformat())

更简单的方法是:

dtime = NetCDF4.num2date(ds['time'][:], ds['time].units)