解剖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. UINavigationController push时,页面卡顿

    1.A push B A.view.backgroundColor 与 B.view.backgroundColor 不一致. 2. AssistiveTouch打开 关闭则不会出现卡顿情况 3.增加 ...

  2. Linux的学习之路

    linux的安装配置.常用命令: 基本上学习任务: 1.在VMware(9)虚拟机上安装Linux操作系统(安装CentOs操作系统) 2.了解Linux操作系统 3.通过XShell工具操作Linu ...

  3. android sdk镜像站点

    http://android-mirror.bugly.qq.com:8080/include/usage.html Windows A. 打开Android SDK Manager  B. 设置代理 ...

  4. 手机GPS为什么能在室内定位?

      为什么手机在室内也能定位?大部分人知道手机会通过GPS进行定位,其实手机定位系统并不是和我们的RTK完全一样的,因为那样就无法解释为何在室内也能定位了,这里我来科普一下智能手机的那些定位方法.   ...

  5. JSON字符串解析

    有时保存在数据库的数据是一串json字符串,需要进行读取的时候就需要解析操作. 简单介绍两种: 1.net.sf.json.* 2.com.alibaba.fastjson.* 需要的包自行下载. 第 ...

  6. 关于echarts3地图下钻省市

    最近关于echarts3弄了个地图下钻,也许是因为运气不好,开始上来需要传递到的城市是成都,结果成都地图(js)加载下来总是挤到了一起,好尴尬,各方实验查找后发现原来是js文件中,成都市地图有个县市并 ...

  7. laravel中如何写验证码文件,并防止中文乱码.

    本例为生成中文验证码,专为laravel而生. //控制器: public function getVcode(Request $request){ $width=845; $height=125; ...

  8. py2exe 打包scipy时遇到的问题

    最近写了个小程序,用PyQt5做的界面,写完之后用py2exe打包成独立的exe文件,运行正常. 后来由于需要,调用SciPy.io.loadmat,改写setup.py,打包之后运行错误,提示: T ...

  9. 一个实现了View接口的Fragment

    小程序并不新鲜,模式上先有百度轻应用,后有支付宝的各类小服务,再来还有腾讯自家QQ右下角的应用宝:技术上也就是FaceBook RN的那一套.一个技术上无创新,形式上无创意的事物,凭什么勾起了开发者们 ...

  10. Build Android Webrtc Libjingle Library On Ubuntu

    Our team is developing an app to help people solve problem face to face. We choose webrtc protocol a ...