一些复合类型进行范式分解是没有必要的,尤其是一些统一模型的情况下
- SET NOCOUNT ON
- DECLARE @i TimeBalance
- SET @i = CAST('D/2015-1-1/7' AS TimeBalance)
- SELECT @i
- SELECT @i.ToString()
- SELECT @i.ToTimeString()
- SELECT @i.Distance() AS Distance;
- WITH a AS ( SELECT '100' s ,
- '' m
- UNIONALL
- SELECT '281474976710693' s ,
- '37次' m
- UNIONALL
- SELECT 'Y/2015-1-5/1' s ,
- '包年' m
- UNIONALL
- SELECT 'M/2015-1-5/11' s ,
- '包个月' m
- UNIONALL
- SELECT 'D/2015-1-1/7' s ,
- '包天' m
- UNIONALL
- SELECT '1500438729850887' s ,
- '包天' m
- UNIONALL
- SELECT 'H/2015-1-5 8:30/10' s ,
- '包小时' m
- )
- SELECT m + '' + s ,
- t.ToString() string ,
- t.ToHex() hex ,
- t.ToTimeString() timeString ,
- t.ToValue() value ,
- t.Distance() distance
- FROM ( SELECT s ,
- m ,
- CAST (s AS TimeBalance) t
- FROM A
- ) tt
相关资料:
TSql vs. SQL CLR Performance Analysis
- using System;
- using System.Data;
- using System.Data.SqlClient;
- using System.Data.SqlTypes;
- using Microsoft.SqlServer.Server;
- /// <summary>
- /// 时间钱包余额类型
- ///
- /// </summary>
- /// <remarks>
- /// 基于长整型,结构如下:
- /// 包时类型2B,起始时间UTC秒数4B,时间总长2B(单位同类型决定)
- /// <p>包时类型:0不包时1秒2分3时4日5月6年</p>
- /// </remarks>
- /// <see cref="https://msdn.microsoft.com/en-us/library/ms131086.aspx"/>
- [Serializable]
- [Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native)]
- publicstruct TimeBalance : INullable
- {
- publicoverridestring ToString()
- {
- switch (type)
- {
- case 0:
- case 1:
- return ToValue().ToString();
- default:
- returnstring.Format("{0}/{1}/{2}", (TimeEnum)type, UTCSecondToDateTime(startSecond).ToString("yyyy-MM-dd HH:mm:ss"), value);
- }
- }
- publicstring ToHex()
- {
- return type.ToString("X4") +"" + startSecond.ToString("X8") + value.ToString("X4");
- }
- publicstring ToTimeString()
- {
- switch (type)
- {
- case 0:
- case 1:
- return ToValue().ToString();
- default:
- TimeEnum typeEnum = (TimeEnum)type;
- string format = "";
- switch (typeEnum)
- {
- case TimeEnum.S:
- default:
- format = "HH:mm:ss";
- break;
- case TimeEnum.Mi:
- format = "dd HH:mm";
- break;
- case TimeEnum.H:
- format = "MM-dd HH";
- break;
- case TimeEnum.D:
- format = "yyyy-MM-dd";
- break;
- case TimeEnum.M:
- format = "yyyy-MM";
- break;
- case TimeEnum.Y:
- format = "yyyy";
- break;
- }
- returnstring.Format("{0}/{1}/{2}", (TimeEnum)type, UTCSecondToDateTime(startSecond).ToString(format), EndTime().ToString(format));
- }
- }
- publiclong ToValue()
- {
- switch (type)
- {
- case 0:
- case 1:
- returnvalue;
- default:
- return ((long)type << 48) + ((long)startSecond << 16) + value;
- }
- }
- publicstatic TimeBalance Parse(SqlString s)
- {
- if (s.IsNull)
- return Null;
- try
- {
- TimeBalance u = new TimeBalance();
- if (s.Value.Contains("/"))
- {
- u.type = (short)(TimeEnum)Enum.Parse(typeof(TimeEnum), (s.Value.Split('/')[0]));
- u.startSecond = DateTimeToUTCSecond(DateTime.Parse(s.Value.Split('/')[1]));
- u.value = long.Parse(s.Value.Split('/')[2]);
- }
- else
- {
- byte[] bs = BitConverter.GetBytes(long.Parse(s.Value));
- u.type = BitConverter.ToInt16(bs, 6);
- switch (u.type)
- {
- case 0:
- u.value = long.Parse(s.Value);
- break;
- case 1:
- u.value = BitConverter.ToInt16(bs, 0);
- break;
- default:
- u.startSecond = BitConverter.ToInt32(bs, 2);
- u.value = BitConverter.ToInt16(bs, 0);
- break;
- }
- }
- return u;
- }
- catch (Exception ex)
- {
- thrownew Exception(s.Value + "\r\n" + ex.ToString());
- }
- }
- publicbool IsNull
- {
- get
- {
- // 在此处放置代码
- return _null;
- }
- }
- publicstatic TimeBalance Null
- {
- get
- {
- TimeBalance h = new TimeBalance();
- h._null = true;
- return h;
- }
- }
- publiclong Distance()
- {
- returnvalue;
- }
- public DateTime EndTime()
- {
- short v = (short)(value & 0xffff);
- TimeEnum typeEnum = (TimeEnum)type;
- switch (typeEnum)
- {
- // case TimeEnum.N:
- case TimeEnum.S:
- default:
- return UTCSecondToDateTime(startSecond).AddSeconds(v);
- case TimeEnum.Mi:
- return UTCSecondToDateTime(startSecond).AddMinutes(v);
- case TimeEnum.H:
- return UTCSecondToDateTime(startSecond).AddHours(v);
- case TimeEnum.D:
- return UTCSecondToDateTime(startSecond).AddDays(v);
- case TimeEnum.M:
- return UTCSecondToDateTime(startSecond).AddMonths(v);
- case TimeEnum.Y:
- return UTCSecondToDateTime(startSecond).AddYears(v);
- }
- }
- #region 获取UTC
- publicstaticint DateTimeToUTCSecond(DateTime dateTime)
- {
- return (int)dateTime.ToUniversalTime().Subtract(UTC).TotalSeconds;
- }
- static DateTime UTCSecondToDateTime(int second)
- {
- return UTC.AddSeconds(second).ToLocalTime();
- }
- #endregion
- // 这是占位符成员字段
- publicint startSecond;
- publicshort type;
- publiclongvalue;
- staticreadonly DateTime UTC = TimeZoneInfo.ConvertTimeToUtc(new DateTime(1970, 1, 1), TimeZoneInfo.Utc);
- // 私有成员
- privatebool _null;
- }
- publicenum TimeEnum
- {
- N = 0,
- T = 1,//Times
- S = 2,
- Mi = 3,
- H = 4,
- D = 5,
- M = 6,
- Y = 7
- }