解剖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 ; }
} public object GetValue(byte[] value)
{
if (value.Length != )
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[] << ) + (value[] << ) + value[]; return new DateTime(, , ).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(, , ), Convert.ToDateTime(type.GetValue(input)));
input = new byte[] { 0x71, 0x5c, 0x0b };
Assert.AreEqual(new DateTime(, , ), Convert.ToDateTime(type.GetValue(input)));
}
[Test]
public void Length()
{
var type = new SqlDate();
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[]));
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[]));
}
}
}

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 / / /
分钟 X / / %
秒 X / %
毫秒 X % * 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 ; }
} public object GetValue(byte[] value)
{
if (value.Length != )
throw new ArgumentException("Invalid value length: " + value.Length); int time = BitConverter.ToInt32(value, );
int date = BitConverter.ToInt32(value, ); return new DateTime(, , , time///, time//%, time/%, (int)Math.Round(time%*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(, , , , , , ), (DateTime)type.GetValue(input));
input = new byte[] { 0xb6, 0x87, 0xf0, 0x00, 0xd1, 0x8b, 0x00, 0x00 };
Assert.AreEqual(new DateTime(, , , , , , ), (DateTime)type.GetValue(input));
input = new byte[] { 0x2d, 0xfd, 0x1c, 0x01, 0x4a, 0x75, 0x00, 0x00 };
Assert.AreEqual(new DateTime(, , , , , , ), (DateTime)type.GetValue(input));
input = new byte[] { 0xff, 0x81, 0x8b, 0x01, 0x7f, 0x24, 0x2d, 0x00 };
Assert.AreEqual(new DateTime(, , , , , , ), (DateTime)type.GetValue(input));
}
[Test]
public void Length()
{
var type = new SqlDateTime();
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[]));
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[]));
}
}
}

SqlSmallDateTime实现

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

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

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

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

部分     计算
小时 X /
分钟 X %
public class SqlSmallDateTime : ISqlType
{
public bool IsVariableLength
{
get { return false; }
} public short? FixedLength
{
get { return ; }
} public object GetValue(byte[] value)
{
if (value.Length != )
throw new ArgumentException("Invalid value length: " + value.Length); ushort time = BitConverter.ToUInt16(value, );
ushort date = BitConverter.ToUInt16(value, ); return new DateTime(, , , time / , time % , ).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(, , , , , ), Convert.ToDateTime(type.GetValue(input)));
input = new byte[] { 0x49, 0x03, 0x99, 0x09 };
Assert.AreEqual(new DateTime(, , , , , ), Convert.ToDateTime(type.GetValue(input)));
}
[Test]
public void Length()
{
var type = new SqlSmallDateTime();
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[]));
Assert.Throws<ArgumentException>(() => type.GetValue(new byte[]));
}
}
}

第四篇完

解剖SQLSERVER 第四篇 OrcaMDF里对dates类型数据的解析(译)的更多相关文章

  1. 解剖SQLSERVER 第五篇 OrcaMDF里读取Bits类型数据(译)

    解剖SQLSERVER 第五篇  OrcaMDF里读取Bits类型数据(译) http://improve.dk/reading-bits-in-orcamdf/ Bits类型的存储跟SQLSERVE ...

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

    解剖SQLSERVER 第八篇  OrcaMDF 现在支持多数据文件的数据库(译) http://improve.dk/orcamdf-now-supports-databases-with-mult ...

  3. 解剖SQLSERVER 第七篇 OrcaMDF 特性概述(译)

    解剖SQLSERVER 第七篇  OrcaMDF 特性概述(译) http://improve.dk/orcamdf-feature-recap/ 时间过得真快,这已经过了大概四个月了自从我最初介绍我 ...

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

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

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

    解剖SQLSERVER 第六篇  对OrcaMDF的系统测试里避免regressions (译) http://improve.dk/avoiding-regressions-in-orcamdf-b ...

  6. 解剖SQLSERVER 第十三篇 Integers在行压缩和页压缩里的存储格式揭秘(译)

    解剖SQLSERVER 第十三篇    Integers在行压缩和页压缩里的存储格式揭秘(译) http://improve.dk/the-anatomy-of-row-amp-page-compre ...

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

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

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

    解剖SQLSERVER 第十一篇    对SQLSERVER的多个版本进行自动化测试(译) http://improve.dk/automated-testing-of-orcamdf-against ...

  9. 解剖SQLSERVER 第三篇 数据类型的实现(译)

    解剖SQLSERVER 第三篇  数据类型的实现(译) http://improve.dk/implementing-data-types-in-orcamdf/ 实现对SQLSERVER数据类型的解 ...

随机推荐

  1. 40多个纯CSS绘制的图形

    本文由码农网 – 陈少华原创,转载请看清文末的转载要求. 今天在国外的网站上看到了很多看似简单却又非常强大的纯CSS绘制的图形,里面有最简单的矩形.圆形和三角形,也有各种常见的多边形,甚至是阴阳太极和 ...

  2. idea debug 变慢

    在run模式下很快大概30s左右,在debug模式下花了2分钟,debug信息不断输出: Returning cached instance of singleton bean....网上查了一下,说 ...

  3. HTTP Client工具类

    HTTP Client工具类: import org.apache.http.Header;import org.apache.http.HttpEntity;import org.apache.ht ...

  4. 判断是否字符串是否是JSON

    很多PHPER在开发中数据交互时用的JSON格式,但是没有做很严格的校验,比如一个串是否是正确的json而直接json_decode($str,true), 个人建议在decode前做下校验,防止因为 ...

  5. NSLock线程锁的使用测试

    测试1:NSLock线程锁是不是单例? 打印: 结论1:NSLock不是单例 测试2:同一个线程锁在不同的地方锁定,是否会有锁定两个? 打印为: 结论2:顺序打印,在不同的地方锁定也可以锁定. 测试3 ...

  6. Django + Apache + 树莓派 搭建内网微信公众号服务器

    其实早在微信开放公众号开发平台时就想弄一个自己的公众号服务器,奈何对web服务器搭建和开发一窍不通,只是注册了一下开发者帐号,并没有采取行动,万恶的拖延症. 前一年,开始接触python,打开了神奇世 ...

  7. python中几个常见的黑盒子之“字典dict” 与 “集合set”

    这里说到"字典dict" 和 "集合set"类型,首先,先了解一下,对于python来说,标准散列机制是有hash函数提供的,对于调用一个__hash__方法: ...

  8. aa4

    // 初始化地图 var BMapExt = new BMapExtension(domMain, BMap, require('echarts'), require('zrender')); var ...

  9. SQL Server 2008通过LinkServer操作ORACLE

    时光荏苒~~ 最近项目有需求需要通过SQL Server2008中的数据自动更新到ORACLE中,其实,一开始肯定会想到触发器,因为可以保证实时性. 方案一: 首先,我很确定的一件事情就是MSSQL中 ...

  10. Centos 基础开发环境搭建之Maven私服nexus

    hmaster 安装nexus及启动方式 /usr/local/nexus-2.6.3-01/bin ./nexus status Centos 基础开发环境搭建之Maven私服nexus . 软件  ...