PLCのUnixの時刻をWindowsの時刻に変換する方法

概要

PLC NXシリーズは1970-01-01 00:00:00からの経過時間を1ns毎にカウントした値を時刻としています
Windowsは1601-01-01 00:00:00からの経過時間を100ns毎にカウントした値を時刻としています

NX/NJ Windows
開始時刻 1970-01-01 (Unixエポック) 1601-01-01 (NTタイムエポック)
インターバル 1ns 100ns


ここではC#を使ってPLCの時刻データをバイト配列で読み出したばあいに変換する方法を紹介します

データ型の対応表
NX/NJ Windows
DATE DateTime
DATE_AND_TIME DateTime
TIME TimeSpan
TIME_OF_DAY TimeSpan

DATE型、DATE_AND_TIME型

DateTime.AddTicksを使ってDateTime型に変換します

Unixの時刻型変数の値(カウント数)を1/100にして
Windowsの1970-01-01 00:00:00の時刻のカウント数に加算してWindowsの時刻型変数とします

private static DateTime UNIX_EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, 0);

// PLCにあるDATE_AND_TIME型を含む構造体をCompoletでバイト配列に読み出す(例: Compoletの場合)
byte[] value = compolet1.ReadValiable("struct1");

// バイト配列のうちDATE_AND_TIME型のバイト位置からINT64で数値に変換して1ns単位を100ns単位に合わせる
// Unixの時刻型の基準位置からの経過時間としてValにセットする
ByteOffset = 0
DateTime val = UNIX_EPOCH.AddTicks(BitConverter.ToInt64(value, ByteOffset) / 100);

								

TIME型、TIME_OF_DAY型

DATE型と同様にTimeSpan型に変換します

private static DateTime UNIX_EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, 0);

// PLCにあるDATE_AND_TIME型を含む構造体をCompoletでバイト配列に読み出す(例: Compoletの場合)
byte[] value = compolet1.ReadValiable("struct1");

// バイト配列のうちTIME型のバイト位置からINT64で数値に変換して1ns単位を100ns単位に合わせる
// Unixの時刻型の基準位置からの経過時間としてValにセットする
ByteOffset = 8
TimeSpan val = new TimeSpan(BitConverter.ToInt64(value, ByteOffset) / 100);