TimeZone 时区 (JS .NET JSON MYSQL)

来源参考 : http://www.cnblogs.com/qiuyi21/archive/2008/03/04/1089456.html

来源参考 : http://walkingice.blogspot.com/2014/08/javascript-timezone.html?m=1 (夏令时)

 

有些跨国项目有时区计算的要求,虽然我到目前也没接过这种大项目,但还是先了解一下呗!

整个地球分为二十四时区, 从 -12:00 到 +13:00  

UTC(Universal Time Coordinated) 就是 +0:00 算是统一的时间制度,

GMT(Greenwich Mean Time) 和 UTC 可以看作是相同的 (它们都是英国伦敦的时间)

PST (pacific standard time -08:00) 也挺红的. 

DST ( Daylight Saving Time 夏令时)  不是每个地区都有,它算是一个机制,用于节约能源,做法是在夏季左右把时间调后 1小时,然后又在夏季结束后调回1小时

这个是会影响到时区的,比如 "Sun Mar 09 2014 01:59:00 GMT-0500 (EST)" -> "Sun Mar 09 2014 03:00:00 GMT-0400 (EDT)" . 2点不会出现,因为时间被调后了1小时, -0500 变 -0400 了

 

好,基本上有个时区概念了。那么我们来看看在 js,.net,json,mysql 之前它们对于时区的做法的区别。

先说说 javascript 吧 .

        var date = new Date(); //返回当前本地时间对象,所以不同地区会有不同结果.

        var timezone = date.getTimezoneOffset(); //返回当前地区的时区-分钟 (比如新加坡是 +08:00 , 那么结果就是-480咯,这个是会依据当地的 "夏令时" 的哦!)   

        var strDate = date.toISOString(); //把日期对象转换成string(并且是UTC的时间),它的各式是 2014-11-23T15:01:31.912Z 

        var date = new Date("2014-11-23T15:01:31.912Z"); //str to date , Z表示 UTC 所以,它会把时间依据当地时区做+-然后返回日期对象

        var date = new Date("2014-11-23T15:01:31.912+01:00"); //+01:00 表示这个时间保存时的时区, 会先把这个时间转去 UTC 在 转去本地. -1小时变成UTC,+8小时变成date(比如新加坡)
     //c# 的格式是这样 "yyyy-MM-ddTHH:mm:ss.fffffff%K"

需要清楚string的2种格式写法 (Z 和 +) Z表示日期是个UTC +0:00 , +格式更好,能表示记入时的时区, 之后也还可以转换成UTC 

在c# DateTimeOffset.tostring() default 会出这个格式 "yyyy/MM/dd HH:mm:ss %K" js可以处理,

那么在 mssql 中保持的格式是这样的 "yyyy-MM-dd HH:mm:ss.fffffff %K" js不可以处理

那么一般上我们就直接用 toString就好,那么如果真的要出毫秒的话, 那么就用 "yyyy-MM-ddTHH:mm:ss.fffffff%K" 这个js可以处理.

而外说 : SQL server 如果要set default datetimeOffset 的话用 (sysdatetimeoffset())

    前端一般上我们要呈现给user看的日期格式是 "yyyy-MM-dd hh:mm:ss a" <- 2014-04-01 08:00:00 AM (angularjs 的 pattern)

    在使用 datepicker 时一般上我们是用 "dd-MMM-yyyy" <- 22-May-2015 (angularjs 的 pattern)

还有一种就是什么都没有注明的,既不是Z也不是+ ,那么就不会做任何计算了。

当 date to string 时(包括json化的时候) date 依据当前的时区做+- 然后输出 Z格式.

而 string to date 的话,Z格式会依据当前时区做+- ,而+格式则会先转去UTC在依据当前时区做+- 

所以前台 to 后台的话都是用Z格式(UTC)的。

后台 to 前台 则可能是 Z 或者 + , 要看后台的输出了。

 

.NET 的部分

   DateTime now = DateTime.Now; //kind = local

    DateTime nowUtc = DateTime.UtcNow; //kind = UTC

    TimeSpan offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); 

    DateTimeOffset dateB = new DateTimeOffset(2008, 8, 26, 23, 1, 48, 000, new TimeSpan(4, 0, 0));//kind = unknow

.net 最好是使用 DateTimeOffset 配合 SQL server 的 DateTimeOffset . 但是因为我是用 MYSQL (目前不支持DateTimeOffset,所以下面内容主要针对MYSQL)

date 对象都有一个kind属性表明这个date是local,utc or unknow .

kind UTC ,

-前台的Z格式来到后台被解析后就是 kind utc 

-DateTime.UtcNow 返回是 utc 

kind Local

-DateTime.Now 返回是 local

-当我们从mysql 的 timestamp类型获取值的时候,kind = local 

kind unknow 

-当我们从mysql 的 datetime 类型获取值的时候 , kind = unknow

需要注意的是,我们从 mysql select资料放入date 时,日期是不会被做任何计算的,只有kind有区别. 

当我们使用JSON.NET做序列化想返回给前台时。它会依据你的kind来决定是要放 + 还是 Z ,但是它不会对你的值做任何计算等. 当遇到unknow的时候它会直接返回一个没有 + 也没有 Z 的格式。

以上这2点容易造成混淆。要注意哦.

基本上只有在 DateTime.Now 时会涉及到server 的local时区时间。MYSQL TO c# or js to c# 都不会做什么计算处理,只要注意标签就好。

JSON.net 和 web service 对于前台的 string "2014-05-05" 是可以直接转换成DateTime的 , hour minute second 是 00:00:00, knid = unknow.

这里提供一个.net中查看时区和convert个个时间时区的方法 

    DateTime dt = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now, TimeZoneInfo.Local);

    dt = TimeZoneInfo.ConvertTimeFromUtc(dt, TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time")); //有考虑到夏令时

    List<string> datas = new List<string>();

    foreach (TimeZoneInfo timeZoneInfo in TimeZoneInfo.GetSystemTimeZones())

    {

        //datas.Add(timeZoneInfo.StandardName);

        datas.Add(timeZoneInfo.DisplayName);

    }

 

MYSQL

datetime 和 timestamp 的区别。

timestamp 会配合 mysql 的local时区做计算。比如你的timzone是 +02:00 . 那么你放一个 02:00点进去。mysql内部会把它转成UTC保存。当select的时候它会把这个UTC时间依据当前的时区做 +- 输出。(这里也容易混淆,要注意哦)

datetime 则不会被时区影响,它只是简单的保存值。

mysql 有个 set time_zone = '+8:00'; 的指令,可以per connection 的转换时区。

主要是MYSQL 进出的时候配合timezone计算的方式要搞懂.

 

总结 : 

其实上面主要只是做了一些基础知识的记入。方便我自己以后看的。

一般在开发的时候,SQL 和 .net 经可能都用 UTC 时间来做业务处理。这样可以避免不同服务器数据库地点的时区造成的混淆。

那么在通讯方便,可以利用访问数据库的指令接口,让我们每个select 都 set time_zone = '+0:00'; 确保是UTC时间 (如果你权限够,最后直接设置数据库的local time)

那么在序列化的时候也可以通过 json.net converter write json 的接口做一些自定义的处理。

javascript 方面。我们也可以自己重写 Date.prototype.toJson 方法来做统一处理。

对于一些只有date 不需要time的,甚至可以选择用string "yyyy-MM-dd" 来代替 datetime . (这样就避开时区的问题了)

最重要的就是搞清楚状况,按你的需求来设计方案。统一规范,调整每个通讯接口。那么因该就可以解决时区的混淆了. 

以后有实际开发的案例我再来重写一篇吧 ^^ 

 

你可能感兴趣的:(timezone)