解剖SQLSERVER 第四篇  OrcaMDF里对dates类型数据的解析(译)

http://improve.dk/parsing-dates-in-orcamdf/

在SQLSERVER里面有几种不同的date相关类型,当前OrcaMDF 支持三种最常用的date类型:date,datetime,smalldatetime

SqlDate实现

date 类型在三种类型之中是最简单的,他是一个3个字节的定长类型,存储了日期值它支持的日期范围从0001-01-01到9999-12-31

默认值是1900-01-01

比较坑爹的是.NET里面还没有任何标准实现能够支持3个字节的整数类型,只有short类型和int类型,但是,他们要不太大要不太小

另外,要正确读取日期值,对于.NET的4字节整型我们必须执行一些转变去获取正确的数字

一旦我们获取到date的值,我们可以创建一个默认的datetime类型并且添加天数进去

public class SqlDate : ISqlType
{public bool IsVariableLength{get { return false; }}public short? FixedLength{get { return 3; }}public object GetValue(byte[] value){if (value.Length != 3)throw new ArgumentException("Invalid value length: " + value.Length);// Magic needed to read a 3 byte integer into .NET's 4 byte representation.// Reading backwards due to assumed little endianness.int date = (value[2] << 16) + (value[1] << 8) + value[0];return new DateTime(1, 1, 1).AddDays(date);}
}

相关测试

using System;
using NUnit.Framework;
using OrcaMDF.Core.Engine.SqlTypes;
namespace OrcaMDF.Core.Tests.Engine.SqlTypes
{[TestFixture]
public class SqlDateTests
{[Test]
public void GetValue()
{
var type = new SqlDate();
var input = new byte[] { 0xf6, 0x4c, 0x0b };
Assert.AreEqual(new DateTime(2028, 09, 09), Convert.ToDateTime(type.GetValue(input)));
input = new byte[] { 0x71, 0x5c, 0x0b };
Assert.AreEqual(new DateTime(2039, 07, 17), Convert.ToDateTime(type.GetValue(input)));
}[Test]
public void Length()
{
var type = new SqlDate();
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[2]));
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[4]));
}
}
}

SqlDateTime实现

date类型只能存储日期,而datetime类型不但能存储date也能存储time

datetime存储8字节定长数据值,第一部分是time(4字节),而第二部分是date(4字节)

计算date部分跟上面介绍date类型基本上一样,不过这一次date部分是一个四字节整数,比上面的例子容易处理多了,上面的date类型是3个字节

time部分存储为自午夜时的ticks数,一个tick就是1/300th 秒,为了显示tick值,我们首先定义一个常量,常量值是10d/3d

time的各个部分实际同样存储在同一个整型值里面(比如时间,分钟,秒,毫秒),所以我们要独立访问这些单独的部分,我们必须

要执行一些转换 (包括取模和相除)

部分     计算
小时   X / 300 / 60 / 60
分钟   X / 300 / 60 % 60
秒     X / 300 % 60
毫秒   X % 300 * 10d / 3d

public class SqlDateTime : ISqlType
{private const double CLOCK_TICK_MS = 10d/3d;public bool IsVariableLength{get { return false; }}public short? FixedLength{get { return 8; }}public object GetValue(byte[] value){if (value.Length != 8)throw new ArgumentException("Invalid value length: " + value.Length);int time = BitConverter.ToInt32(value, 0);int date = BitConverter.ToInt32(value, 4);return new DateTime(1900, 1, 1, time/300/60/60, time/300/60%60, time/300%60, (int)Math.Round(time%300*CLOCK_TICK_MS)).AddDays(date);}
}

相关测试

using System;
using NUnit.Framework;
using OrcaMDF.Core.Engine.SqlTypes;
namespace OrcaMDF.Core.Tests.Engine.SqlTypes
{[TestFixture]
public class SqlDateTimeTests
{[Test]
public void GetValue()
{
var type = new SqlDateTime();
byte[] input;
input = new byte[] { 0x5e, 0x3b, 0x5d, 0x00, 0x25, 0x91, 0x00, 0x00 };
Assert.AreEqual(new DateTime(2001, 09, 25, 05, 39, 26, 820), (DateTime)type.GetValue(input));
input = new byte[] { 0xb6, 0x87, 0xf0, 0x00, 0xd1, 0x8b, 0x00, 0x00 };
Assert.AreEqual(new DateTime(1997, 12, 31, 14, 35, 44, 607), (DateTime)type.GetValue(input));
input = new byte[] { 0x2d, 0xfd, 0x1c, 0x01, 0x4a, 0x75, 0x00, 0x00 };
Assert.AreEqual(new DateTime(1982, 03, 18, 17, 17, 36, 790), (DateTime)type.GetValue(input));
input = new byte[] { 0xff, 0x81, 0x8b, 0x01, 0x7f, 0x24, 0x2d, 0x00 };
Assert.AreEqual(new DateTime(9999, 12, 31, 23, 59, 59, 997), (DateTime)type.GetValue(input));
}[Test]
public void Length()
{
var type = new SqlDateTime();
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[9]));
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[7]));
}
}
}

SqlSmallDateTime实现

Smalldatetime 是一个不错的数据类型当你需要存储范围值内的日期值(1900~2079)并且他能精确到秒

大多数场景下,精确到秒已经足够了,在一个范围的时间间隔内和精确值不需要太精确的情况下会节省很多空间

smalldatetime 数据类型会只占用4个字节,前2个字节存储自午夜的分钟数,后2个字节存储日期,默认值是1900-1-1

处理的方法跟datetime差不多,只不过使用更小的范围

部分     计算
小时    X / 60
分钟    X % 60

public class SqlSmallDateTime : ISqlType
{public bool IsVariableLength{get { return false; }}public short? FixedLength{get { return 4; }}public object GetValue(byte[] value){if (value.Length != 4)throw new ArgumentException("Invalid value length: " + value.Length);ushort time = BitConverter.ToUInt16(value, 0);ushort date = BitConverter.ToUInt16(value, 2);return new DateTime(1900, 1, 1, time / 60, time % 60, 0).AddDays(date);}
}

相关测试

using System;
using NUnit.Framework;
using OrcaMDF.Core.Engine.SqlTypes;
namespace OrcaMDF.Core.Tests.Engine.SqlTypes
{[TestFixture]
public class SqlSmallDateTimeTests
{[Test]
public void GetValue()
{
var type = new SqlSmallDateTime();
var input = new byte[] { 0xab, 0x02, 0x5d, 0x26 };
Assert.AreEqual(new DateTime(1926, 11, 22, 11, 23, 0), Convert.ToDateTime(type.GetValue(input)));
input = new byte[] { 0x49, 0x03, 0x99, 0x09 };
Assert.AreEqual(new DateTime(1906, 9, 24, 14, 1, 0), Convert.ToDateTime(type.GetValue(input)));
}[Test]
public void Length()
{
var type = new SqlSmallDateTime();
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[3]));
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[5]));
}
}
}

第四篇完

解剖SQLSERVER 第四篇 OrcaMDF里对dates类型数据的解析(译)相关推荐

  1. 解剖SQLSERVER 第八篇 OrcaMDF 现在支持多数据文件的数据库(译)

    原文:解剖SQLSERVER 第八篇 OrcaMDF 现在支持多数据文件的数据库(译) 解剖SQLSERVER 第八篇  OrcaMDF 现在支持多数据文件的数据库(译) http://improve ...

  2. 解剖SQLSERVER 第十篇 OrcaMDF Studio 发布+ 特性重温(译)

    解剖SQLSERVER 第十篇  OrcaMDF Studio 发布+ 特性重温(译) http://improve.dk/orcamdf-studio-release-feature-recap/ ...

  3. 第四篇 | C语言中bool类型数据应用

    代码展示: //为了描述逻辑的真假问题,引入关键字_Bool 描述逻辑类型, //在stdbool.h中定义bool代表_Bool,定义关键字true和false. #include<stdio ...

  4. 解剖SQLSERVER 第六篇 对OrcaMDF的系统测试里避免regressions(译)

    原文:解剖SQLSERVER 第六篇 对OrcaMDF的系统测试里避免regressions(译) 解剖SQLSERVER 第六篇  对OrcaMDF的系统测试里避免regressions (译) h ...

  5. 解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译)

    解剖SQLSERVER 第十七篇 使用 OrcaMDF Corruptor 故意损坏数据库(译) http://improve.dk/corrupting-databases-purpose-usin ...

  6. 解剖SQLSERVER 第十一篇 对SQLSERVER的多个版本进行自动化测试(译)

    原文:解剖SQLSERVER 第十一篇 对SQLSERVER的多个版本进行自动化测试(译) 解剖SQLSERVER 第十一篇    对SQLSERVER的多个版本进行自动化测试(译) http://i ...

  7. 第四篇:由浅入深,虚拟机常量池底层解析

    文章目录 一.前言 二.常量池的引入:从常量到常量池 2.1 常量 2.2 Class文件中的常量池 2.3 方法区中的运行时常量池 2.4 常量池的好处 三.常量池的介绍:JVM三种常量池 3.1 ...

  8. Excel催化剂开源第50波-Excel与PowerBIDeskTop互通互联之第四篇

    答应过的全盘分享,也必承诺到底,此篇PowerBI功能分享的最后一篇,讲述如何导出数据模型的元数据,笔者定义其为模型的数据字典. 此篇对应功能实现出自:第6波-导出PowerbiDesktop模型数据 ...

  9. spring之旅第四篇-注解配置详解

    spring之旅第四篇-注解配置详解 一.引言 最近因为找工作,导致很长时间没有更新,找工作的时候你会明白浪费的时间后面都是要还的,现在的每一点努力,将来也会给你回报的,但行好事,莫问前程!努力总不会 ...

最新文章

  1. The specified child already has a parent. You must call removeView() on the
  2. C# 实现基于ffmpeg加虹软的人脸识别
  3. LeetCode K-diff Pairs in an Array
  4. pywebQQ-----linux下webQQ的替换者
  5. 总线上加三个终端电阻可以吗_汽车维修中CAN总线的常规检修方法!
  6. 小程序分享到朋友圈_如何给小程序添加分享朋友圈
  7. 给公司省下了300万美元,只因选对了BI工具
  8. 库克斯坦福大学毕业演讲批评硅谷现状:我们有责任改变方向
  9. 给出如下公式的python表达式7+9i+2xcos66_这100道练习,带你玩转Numpy
  10. 针对不同手机系统的LBS地图定位解决方案
  11. 【亚洲微软研究院】带你8篇论文梳理BERT相关模型进展与反思
  12. Java读取文本文件中文乱码问题
  13. 全网首发:解决JDK绘制位图字体的旋转位置错误
  14. 图解机器学习算法 | 从入门到精通系列教程(机器学习通关指南·完结)
  15. B端产品经理知识框架
  16. JavaScript代码收集
  17. 普罗米修斯清除历史数据
  18. vue3+Typescript---Composition API(常用部分)学习笔记(二)
  19. ML_12 Sum-Produkt Networks 和积网络
  20. BLE4.2链路层(LL)安全机制-LL Privacy

热门文章

  1. VTK:IO之ReadPLY
  2. Qt Creator管理工作区
  3. OpenGL indexedCube索引多维数据集的实例
  4. C语言快速排序 quick sort 算法(附完整源码)
  5. vector删除数据时有什么需要注意的吗 ?
  6. QML使用数据来模拟天气预报
  7. QT的QStyleOption类的使用
  8. 经典C语言程序100例之三五
  9. c支限界算法语言n皇后问题分,算法(八)-回溯法-N皇后问题
  10. 1.18.2.Table APISQL(概念与通用API、两种计划器(Planner)的主要区别、创建 TableEnvironment、临时表、永久表、创建表、虚拟表、Connector 等)