相关文章推荐
暴走的充值卡  ·  Spark ...·  1 年前    · 
微醺的小熊猫  ·  Eclipse ...·  1 年前    · 

如果系统不考虑全球化的话,那么我们不用考虑时区的问题,因为我们可以认为中国境内的计算机全部用的是北京时间。

1. 时区的来源和划分

地球自转一圈是360度,共24小时,所以1小时15度,即:15度就是1个时区。

国际定义了本初子午线(0度经线)的位置在英国伦敦 格林尼治天文台 ,自然世界时(UTC)也是指的 格林尼治天文台 (GMT)那里的时间。

认为北京处在东经120度线上,也就是东八区上,所以北京相比UTC时间有8个小时的时差。

由于地球自西向东转,所以北京比格林尼治最先接触阳光,自然就认为北京的时间比格林尼治快8个小时。

比如说:
2020-01-01 00:00:00 +00:00 : 表示格林尼治此时正值午夜凌晨。
但用北京时间表示为 2020-01-01 00:08:00 +08:00 ,即:北京此时天已经亮了,人们正在准备上班。

为什么会有北京时间,全世界都用一个UTC时间不就行嘛?

世界那么大,各地都有自己的习惯,如果突然统一起来,真的不习惯。
比如说,按照UTC时间,我们应该午夜凌晨正在上班的路上,这听起来就很疯狂。。。

2. 全国统一用北京时间吗?新疆的也用北京时间?

1949年建国后,国家就规定统一用北京时间了。
在这里插入图片描述

新疆地区仅少部分本地居民使用新疆时间,但一般默认是北京时间(不过发布新闻的时候,仍能看到“北京时间”、“新疆时间”的字样)。

为什么新疆要使用北京时,从时区上来看,它们相差有2个时区呢?

解释:
比如说奥运会八点开始,那么:
北京新闻就报道,八点开始
新疆报道,十点开始
四川报道,九点开始
各地都不同,这样不就乱了套吗?所以就有了北京时间这个统一标准。

统一时间后,生活作息会有什么差别?

北京:8:00–12:00
新疆:10:00–14:00

北京:1:30–17:30
新疆:15:30–19:30

另外:对于北京的人,感官上有:新疆天黑的晚、上班晚。但其实是一样的,只不过北京的人习惯了6:30就天亮,18:00就天黑而已。

3. 如果需要国际化,该如何使用时间

前提: http请求头中虽然有关于语言(中文简体、英文?)的信息,但是没有携带客户端时区的信息。

既然如此,我们就要在服务端统一一种时区,这样方便我们开发调试,因为是国人开发的应用,所以就用北京时间即可。

剩下的就是客户端了,因为服务端无法预料客户端的时区,所以为了方便开发,我们可以统一返回携带时区信息的时间串,客户端接收后自行转换即可。

常用的携带时区的时间有下面两种格式:
2020-01-02T01:08:07Z (表示:UTC时间)
2020-01-02 09:08:07 +08:00 (表示:北京时间)

针对这两种格式的转换示例如下(c#):

//北京时间(东八区): 2020-01-02 09:08:07.123
var baseTime = new DateTimeOffset(2020, 01, 02, 09, 08, 07, 123, TimeSpan.FromHours(8));
//常规输出: 不考虑时区
var str = baseTime.ToString("yyyy-MM-dd hh:mm:ss");//2020-01-02 09:08:07
str = baseTime.ToString("yyyy-MM-dd hh:mm:ss.fff");//2020-01-02 09:08:07.123
//考虑时区,形式1
str = baseTime.ToUniversalTime().ToString("yyyy-MM-ddThh:mm:ssZ");//2020-01-02T01:08:07Z
str = baseTime.ToUniversalTime().ToString("yyyy-MM-ddThh:mm:ss.fffZ");//2020-01-02T01:08:07.123Z
//考虑时区,形式2
str = baseTime.ToString("yyyy-MM-dd HH:mm:ss zzz");//2020-01-02 09:08:07 +08:00
str = baseTime.ToString("yyyy-MM-dd HH:mm:ss.fff zzz");//2020-01-02 09:08:07.123 +08:00
//如果当前计算机设置的时区是北京时间(东八区)则输出为true,否则输出false
var parse1 = DateTimeOffset.Parse("2020-01-02 09:08:07.123");
Console.WriteLine($"parse1==baseTime: {parse1 == baseTime}");
//输出true
var parse2 = DateTimeOffset.Parse("2020-01-02T01:08:07.123Z");
Console.WriteLine($"parse2==baseTime: {parse2 == baseTime}");
//输出true
var parse3 = DateTimeOffset.Parse("2020-01-02 09:08:07.123 +08:00");
Console.WriteLine($"parse3==baseTime: {parse3 == baseTime}");

4. 那么c#中的DataTime和DataTimeOffset有什么差别?

相同点: 它们两个都存储了年、月、日、时、分、秒、毫秒信息。

  • DateTimeOffset中还存储了时区信息;
  • 而DateTime中未存储时区信息(虽然有个DateTimeKind,但它是个枚举,只有Unspecified、Utc、Local三个值且默认为Unspecified),它总是认为自己存储的时间的时区是当前计算机设置的时区;

5. 以sqlserver为例看数据库中如何存储时间

sqlserver中的关于时间的类型如下:

  • date:3字节,表示范围:0001-01-01 到 9999-12-31
  • datetime:8字节,表示范围: 1753-01-01 00:00:00 到 9999-12-31 23:59:59
  • datetime2:6-8个字节,表示范围:0001-01-01 00:00:00 到 9999-12-31 23:59:59.9999999
  • smalldatetime:4个字节,表示范围:1900-01-01 00:00:00 到 2079-06-06 23:59:59
  • time:5个字节,表示范围: 00:00:00.0000000 到 23:59:59.9999999
  • datetimeoffset:10个字节,表示范围:0001-01-01 00:00:00 到 23:59:59.9999999,可表示时区

通过上面列举,我们可以发现,除非我们使用datetimeoffset,否则我们是无法保存时区信息的。

其实,对于服务器来说,数据库中存不存储时区并不是那么重要,只要保证web服务器、数据库服务器设置的时区一致即可!!!

推荐sqlserver中使用:datetime2

另外:一般我们常设计列的类型为datetime,而不是datetime2。
其实这有个隐患:当程序中(c#)使用DateTime的默认值,即:0000-01-01时,我们无法插入到数据库中,报错如下:

“从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值”

这个报错,在文章:《c# SqlException: 从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值》中有专门说明。

6. 浏览器端如何显示时间

在 上面【3. 如果需要国际化,该如何使用时间】中建议后端返回的时间携带时区信息,也就是下面两种格式:
2020-01-02T01:08:07Z
2020-01-02 09:08:07 +08:00

那么前端应该怎么显示呢?

幸运的是,js脚本可以直接解析上面两种类型的时间,看下面代码:

> new Date(Date.parse("2020-01-02 09:08:07 +08:00")).toDateString()
>> "Thu Jan 02 2020"
> new Date(Date.parse("2020-01-02 09:08:07 +08:00")).toTimeString()
>> "09:08:07 GMT+0800 (中国标准时间)"
> new Date(Date.parse("2020-01-02T01:08:07Z")).toLocaleDateString()
>> "2020/1/2"
> new Date(Date.parse("2020-01-02T01:08:07Z")).toLocaleTimeString() //由于浏览器是北京时间,所以输出的是9:08,而不是 1:08
>> "上午9:08:07"

7. 关于夏令时

参考:《百度百科:夏令时》

夏令时是个奇怪且别扭的东西,中国曾经实行过6年(1986年到1991年),之后便废除了。

那么什么是夏令时的呢?

因为夏季天亮的早、黑的晚,而人们还是以冬季的时间点作息,导致起的晚浪费了阳光,睡的晚浪费了蜡烛,所以就人为的在夏季到来时的某天夜里2点偷偷的将时间调快1小时,然后在夏季结束时的某天夜里2点偷偷的将时间调慢1小时。

上面的一听就很别扭,还有人为改时间的!!! 调整作息时间不就行了吗!

事实上,我们也仅在1986-1991年执行了6年而已,之后便废除了,现在我们都是夏季和冬季到来时调整作息时间的。

假如,我们使用夏令时会有什么影响呢?

  • 夏季到来时,比如:1986年5月4日,在夜里凌晨2点你的表突然跳到了3点,这样你就少睡了一小时。。。
  • 冬季到来时,比如:1986年9月14日,在夜里凌晨2点你的表突然跳到1点,这样你就多睡了一小时。。。
  • 如果你恰好在这个时间段设置了定时任务,那么,你会发现,你的定时任务可能触发了两次,也可能没触发。。。

虽然我国废除了夏令时,但不代表其他国家也废除了,比如说美国目前就实行夏令时。
但,夏令时在全球已经明显不受欢迎了,

  • 俄罗斯: 实行了很长时间,最终2014年通过杜马法案废除了。
  • 西班牙:还在偷偷改时间。
  • 美国:不仅偷偷改时间,而且各个州的时区不一样,所以重要会议一般都会标注时区。
  • 全球有110多个国家在使用夏令时。
  • 欧盟正在废除夏令时的路上。

另外,想查看哪些地区支持夏令时,可以在电脑的时区设置中发现:
在这里插入图片描述
在这里插入图片描述

由于工作需要我们有时常常需要转化当地时间为其它时区的时间,或是把某一个时区的时间,转成另一个时区。 最近由于用了一些C#的方法,下面小结一下,省得过后自已又忘了。 1。 用如下的方法,可以得到所有的时区信息。 TimeZoneInfo.GetSystemTimeZones() 2。得到时区ID TimeZoneInfo.GetSystemTimeZones()[75].ID
一. 时间的类型 1. 背景   这里为什么要介绍时间类型呢,明明是定时调度篇,原因是在定时任务,任务什么时间开始执行,什么时间结束执行,要用到各种各样的时间模式,虽然这不能算是一个复杂的问题,但在正式介绍Quartz.Net之前,还是很有必要补充一下的,该章节就是解决这类问题的。 2. 时间类型   时间类型主要有两类:DateTimeDateTimeOffset var dateTime = DateTimeOffset.Parse("2022-02-20T13:04+08:00"); Console.WriteLine(dateTime.ToString("yyyy-MM-ddTHH:mmzzz")); 参考文档: c#时区DateTimeDateTimeOffset - .Neter1 - 博客园 (cnblogs.com)
C#DateTime在逻辑上有个非常严重的缺陷: DateTime d = DateTime.Now; DateTime d2 = d.ToUniversalTime(); Console.WriteLine("{0}", d); Console.WriteLine("{0}", d2); var result = (d == d2); Console.WriteLine("...
2.使用场景 例如:mysql数据库datetime字段没有时区概念 ,所以可存DateTimeOffset时区偏移量为0的时间(相当于存UTC时间),取出来按当地时区还原即可 3.常用的DateTimeOffset 的构造 第一种:new DateTimeOffset(2008, 6, 18, 7, 0, 0, new TimeSpan(-5, 0, 0)); 第二种:DateTime b
DateTimeDateTimeOffset 都是 C# 用来表示日期和时间的类型。 DateTime 类型表示一个日期和时间的值,精确到毫秒级别。它包含了年、月、日、时、分、秒和毫秒信息,但没有时区信息。DateTime 类型适合用于表示与时区无关的日期和时间,比如记录事件发生的时间。 DateTimeOffset 类型也表示一个日期和时间的值,但相比于 DateTime,它多了时区信息。DateTimeOffset 包含了年、月、日、时、分、秒和毫秒信息,同时也包含了一个偏移量,指示了此日期和时间与协调世界时(UTC)之间的差距。这使得 DateTimeOffset 类型能够更好地处理跨时区的场景。 你可以使用 DateTime.Now 属性获取当前本地时间,或者使用 DateTime.UtcNow 属性获取当前协调世界时(UTC)时间。 以下是使用 DateTimeDateTimeOffset 的示例: ```csharp // 使用 DateTime 表示一个日期和时间 DateTime dateTime = new DateTime(2022, 1, 1, 12, 0, 0); Console.WriteLine(dateTime); // 输出: 2022/1/1 12:00:00 AM // 使用 DateTimeOffset 表示一个带有时区偏移的日期和时间 DateTimeOffset dateTimeOffset = new DateTimeOffset(2022, 1, 1, 12, 0, 0, TimeSpan.FromHours(8)); Console.WriteLine(dateTimeOffset); // 输出: 2022/1/1 12:00:00 PM +08:00 希望能解答你的问题!如果还有其他问题,请继续提问。