.net 对日期格式转BCD编码

本文介绍了在C语言项目中如何处理BCD编码,特别是将日期YYYYMMDDHHMMSS转换为BCD编码的过程。BCD码是一种用4位二进制表示1位十进制数的编码方式,常见于需要高精度计算的场景。文章提供了一个BCDHelper类,包含ToBCD和FromBCD方法,用于日期字符串到BCD编码的转换,并给出了具体的使用示例。

项目背景

与C语言的相关加密做对接,遇到一个没见过的编码,对日期YYYYMMDDHHMMSS进行转BCD编码

编码原理

BCD码(Binary-Coded Decimal‎),用4位二进制数来表示1位十进制数中的0~9这10个数码,是一种二进制的数字编码形式,用二进制编码的十进制代码。BCD码这种编码形式利用了四个位元来储存一个十进制的数码,使二进制十进制之间的转换得以快捷的进行。这种编码技巧最常用于会计系统的设计里,因为会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点记数法,采用BCD码,既可保存数值的精确度,又可免去使计算机作浮点运算时所耗费的时间。此外,对于其他需要高精确度的计算,BCD编码亦很常用。

实现过程

明白了基本原理接下来就简单了,先把日期依次截取2个字符,然后转换成byte,然后转换成BCD编码的int值即可

注意实现:如果最终的int值小于10,可能需要补0

方法示例

  帮助类

public static class BCDHelper
    {
        public static int ToBCD(byte val)
        {
            int res = 0;
            int bit = 0;
            while (val >= 10)
            {
                res |= (val % 10 << bit);
                val /= 10;
                bit += 4;
            }
            res |= val << bit;
            return res;
        }
        public static byte FromBCD(int vals)
        {
            int c = 1;
            byte b = 0;
            while (vals > 0)
            {
                b += (byte)((vals & 0xf) * c);
                c *= 10;
                vals >>= 4;
            }
            return b;
        }
    }

转换过程

string currtime = DateTime.Now.ToString("yyyyMMddHHmmss"); //时间需要转BCD
int t = BCDHelper.ToBCD(Convert.ToByte(currtime.Substring(i * 2, 2)));

S7.NET 是一个用于与西门子 S7 系列 PLC 进行通信的 .NET 库,支持读写 PLC 的数据块、变量等信息。PLC 中的日期时间信息通常以 `DATE_AND_TIME` 数据类型存储,它占用 8 字节(64 位),分别表示年、月、日、时、分、秒和毫秒。 ### 使用 S7.NET 读取 DATE_AND_TIME 类型数据 在 S7.NET 中,可以通过 `DBRead` 方法从数据块中读取 `DATE_AND_TIME` 类型的数据,然后将其解析为 .NET 中的 `DateTime` 对象。 以下是一个完整的示例代码: ```csharp using S7.Net; using System; class Program { static void Main() { // 创建 PLC 实例(S7-1200/S7-1500 使用正确的 CPU 类型) Plc plc = new Plc(CpuType.S71200, "192.168.0.1", 0, 1); try { // 打开连接 plc.Open(); if (plc.IsConnected) { // 假设 DATE_AND_TIME 存储在 DB1 的偏移量为 0 的位置 byte[] buffer = plc.ReadMemory(MemoryType.DataBlock, 1, 0, 8); // 将字节数组换为 DateTime DateTime parsedTime = ParsePlcDateTime(buffer); Console.WriteLine("PLC 中的日期时间: " + parsedTime); } } catch (Exception ex) { Console.WriteLine("读取失败: " + ex.Message); } finally { // 关闭连接 plc.Close(); } } /// <summary> /// 解析 DATE_AND_TIME 字节数组为 DateTime /// </summary> static DateTime ParsePlcDateTime(byte[] bytes) { if (bytes.Length != 8) throw new ArgumentException("DATE_AND_TIME 必须是 8 字节"); int year = BcdToInt(bytes[0]); int month = BcdToInt(bytes[1]); int day = BcdToInt(bytes[2]); int hour = BcdToInt(bytes[3]); int minute = BcdToInt(bytes[4]); int second = BcdToInt(bytes[5]); int millisecond = (int)(BcdToInt(bytes[6]) * 10); // 毫秒部分通常为 10ms 精度 return new DateTime(year + 2000, month, day, hour, minute, second, millisecond); } /// <summary> /// 将 BCD 编码的字节换为整数 /// </summary> static int BcdToInt(byte b) { return ((b >> 4) * 10) + (b & 0x0F); } } ``` ### 注意事项 - **BCD 编码**:PLC 中的日期时间通常以 BCD(Binary-Coded Decimal)格式存储,因此需要将每个字节拆分为高四位和低四位,分别表示十位和个位。 - **年份偏移**:PLC 中年份通常表示为 00~99,表示 2000~2099。 - **精度问题**:毫秒部分通常以 10ms 为单位存储,因此需要乘以 10 才能得到 .NET 中的毫秒值。 ### 数据结构映射 | PLC 数据类型 | .NET 类型 | 说明 | |--------------------|-----------|--------------------------| | DATE_AND_TIME | DateTime | 8 字节,包含日期和时间 | | TIME_OF_DAY (TOD) | TimeSpan | 表示一天中的时间 | | DATE | DateTime | 仅包含日期 | | TIME | TimeSpan | 表示经过的时间 |
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值