c# - 如何使用 protobuf-net 将 C# 日期时间转换为 Python 日期时间?
问题描述
我已经使用它的消息结构的原型文件(struct_pb2.py)序列化了一个 C#DateTime.Now
对象数组,并在 Python 中打开了该文件。protobuf-net
// The struct definition in C#
[ProtoContract]
public struct struct_tick
{
[ProtoMember(1)]
public uint[] arr_currentIndex;
[ProtoMember(2)]
public string[] arr_currentType;
[ProtoMember(3)]
public DateTime[] arr_currentTime; // <- for DateTime.Now objects
public struct_tick(byte size_index, byte size_type, byte size_time)
{
arr_currentIndex = new uint[size_index];
arr_currentType = new string[size_type];
arr_currentTime = new DateTime[size_time];
}
}
syntax = "proto3";
import "google/protobuf/timestamp.proto";
message struct_tick
{
repeated uint32 arr_currentIndex = 1;
repeated string arr_currentType = 2;
repeated google.protobuf.Timestamp arr_currentTime = 3;
}
它在 Python 中打开得很好,但是如何正确地将 C# datetime 对象转换为 Python datetime 对象?让我感到困惑的是文件的日期时间数组中显示的内容。
>>> struct = struct_pb2.struct_tick()
>>> with open(filename, "rb") as f:
>>> struct.ParseFromString(f.read())
>>> lst_time = [ time for time in struct.arr_currentTime]
>>> lst_time[:5]
[seconds: 1573571465
nanos: 335624000
, seconds: 1573571465
nanos: 335624000
, seconds: 1573571465
nanos: 335624000
, seconds: 1573571465
nanos: 335624000
, seconds: 1573571465
nanos: 335624000
]
>>> lst_time[-5:]
[seconds: 1573571465
nanos: 337636000
, seconds: 1573571465
nanos: 337636000
, seconds: 1573571465
nanos: 337636000
, seconds: 1573571465
nanos: 337636000
, seconds: 1573571465
nanos: 337636000
]
当我在 C# 中读取同一个文件时,第一个 datetime 对象代表 21:59:39.7450630,最后一个对象代表 23:38:50.3848014,这意味着有将近 2 小时的间隔。但是 Python 中显示的内容完全不同。
是不是因为我DateTime
在序列化的google.protobuf.Timestamp
时候用的,反序列化的时候用的?如何正确转换它们?
添加
这是接收数据并将其写入其结构中的数组的回调函数:
static void Handler_Real(string szCode)
{
string code = REAL_TR.GetData("Out", "sym");
string currentType = REAL_TR.GetData("Out", "cg");
DateTime currentTime = DateTime.Now;
if (dic_codeToTRstructCounter[code] == arraySize)
{
dic_codeToTRstructCounter[code] = 0;
using (var fileStream = new FileStream(dic_codeToTRfilename[code], FileMode.Append))
{
Serializer.Serialize(fileStream, dic_codeToTRstruct[code]);
}
}
dic_codeToTRstruct[code].arr_currentIndex[dic_codeToTRstructCounter[code]] = dic_codeToTRCounter[code];
dic_codeToTRstruct[code].arr_currentType[dic_codeToTRstructCounter[code]] = currentType;
dic_codeToTRstruct[code].arr_currentTime[dic_codeToTRstructCounter[code]] = currentTime;
dic_codeToTRstructCounter[code] += 1;
dic_codeToTRCounter[code] += 1;
}
这就是我在 C# 中读取文件的方式,效果很好。
using (var fileStream = new FileStream("file.bin", FileMode.Open))
{
struct_tick str = Serializer.Deserialize<struct_tick>(fileStream);
for (int startNum = 0; startNum < str.arr_currentIndex.Length; startNum++)
{
string str_print = string.Format("{0}, {1}, {3}", str.arr_currentIndex[startNum],
str.arr_currentType[startNum],
str.arr_currentTime[startNum].ToString("HH:mm:ss.fffffff"));
listBox1.Items.Add(str_print);
}
}
这就是我在 Python 中读取相同文件的方式
def convert_TRtoArray(filename):
struct = struct_pb2.struct_TR()
with open(filename, "rb") as f:
struct.ParseFromString(f.read())
lst_currentIndex = [ indexNum for indexNum in struct.arr_currentIndex ]
lst_currentType = [ type for type in struct.arr_currentType ]
lst_currentTime = [ time for time in struct.arr_currentTime ]
当我检查时lst_currentTime
,虽然 C# 程序已经收到了 2 个小时的数据,但值与上面一样。
解决方案
在像 Protobuf 这样的二进制可序列化流中使用 DateTime 不是一个好习惯。最好将 DateTime 值转换为其他值,例如纪元时间甚至字符串,然后对纪元时间或字符串值使用序列化。否则,您将无法正确恢复该字段的内容。
推荐阅读
- ssl - 长生不老药:将 :inets:start 放入函数有什么优点/缺点?
- sas - 如何将 5 个相同的数据集合并为一个数据集,然后求值的总和
- android - Branch.io SDK 无法在 Unity3D 中的 Android 构建上初始化
- ios - Firebase updateChildValues 函数会阻止其他 Firebase 函数
- python-3.x - 有没有办法从 Python Pendulum 给定偏移量获取 TZ 数据库名称?
- java - 这是在 Android 应用程序上重试 API 调用的按钮的正确方法吗?
- c++ - 从 Bison/Flex 中的命令行获取 2 个输入
- latex - 如何在引用的段落下方自动显示表格
- excel - if语句计算else复制粘贴?
- python - 使用 tornado.httpclient.AsyncHTTPClient 时如何修复“RuntimeWarning: Enable tracemalloc to get the object allocation traceback”?