CS5L12——日期和时间
CS5L12——日期和时间
本章代码关键字
1 | DateTime //C#提供给我们处理日期和时间的结构体 |
目前学习过和时间相关的内容
目前我们只在Unity当中学习过 Time 类,我们可以通过 Time
获取当前游戏相关的时间,比如帧间隔时间,游戏运行的时间和帧数等等内容
但是我们并没有学习过和真实世界时间相关的内容,比如如何得知当前时间的 年、月、日、时、分、秒
本章就是学习的就是真实时间相关的内容
时间对于我们的作用
在游戏开发当中我们经常会有和时间打交道的内容,比如每日签到、活动倒计时、建造时间、激活时间等等的功能
如果想要完成这些功能,仅仅用Unity提供给我们的Time类是远远不够用的
所以我们需要学习专门的日期和时间相关的知识,才能制作某些功能需求
而 C# 便提供了对应的结构方便我们处理时间相关逻辑
-
DateTime
日期结构体 -
TimeSpan
时间跨度结构体
一些关于时间的名词说明
-
时间单位
1s 秒 = 1000ms 毫秒
1ms 毫秒 = 1000μs 微妙
1μs 微妙 = 1000ns 纳秒 -
格里高利历
格里高利历一般指公元, 公元,即公历纪年法
目前我们所说公历,就是格里高利历,比如2023年就是从公元元年开始算起的两千二十三年 -
格林尼治时间(GMT)
格林尼治标准时间,是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线
地球每天的自转是有些不规则的,而且正在缓慢减速,所以,格林尼治时间已经不再被作为标准时间使用
现在的标准时间就是协调世界时(UTC) -
协调世界时(UTC)
又称世界统一时间、世界标准时间、国际协调时间
UTC协调世界时即格林尼治平太阳时间,是指格林尼治所在地的标准时间,也是表示地球自转速率的一种形式
UTC基于国际原子时间,通过不规则的加入闰秒来抵消地球自转变慢的影响,是世界上调节时钟和时间的主要时间标准 -
时间戳
从1970年1月1日(UNIX时间戳的起点时间)到现在的时间(单位为秒)
计算机时间和众多的编程语言的时间都是从1970年1月1日开始算起,
因为很多编程语言起源于UNIX系统,而UNIX系统认为1970年1月1日0点是时间纪元
所以我们常说的UNIX时间戳是以1970年1月1日0点为计时起点时间的原因:
最初计算机操作系统是32位,而时间也是用32位表示,我们知道32位能代表的最大十进制数是2147483647
1年是365天,总秒数是3153 6000,那么 2147483647/31536000 = 68.1年
也就是说因为早期用32位来表示时间,最大的时间间隔是68年,而最早出现的UNIX操作系统考虑到计算机产生的年代和应用的
时限综合取了1970年1月1日作为UNIX TIME
的纪元时间(开始时间)
DateTime
命名空间:System
DateTime
是 C# 提供给我们处理日期和时间的结构体
DateTime
对象的默认值和最小值是 ** 0001年1月1日00:00:00(午夜),** 最大值可以是 9999年12月31日晚上11:59:59
初始化与时间表示
1 | DateTime dt = new DateTime(2023, 11, 1, 21, 38, 00, 500); //以年、月、日、时、分、秒、毫秒初始化(一般可以不需要全部填入,有多个重载) |
主要参数:
年、月、日、时、分、秒、毫秒
**或者:**ticks
:以格里高利历00:00:00.000年1月1日以来的100纳秒间隔数表示,一般是一个很大的数字(该重载几乎不使用)
次要参数:
DateTimeKind
:日期时间种类:
-
Local
:本地时间(默认参数,以系统上设置的时间为准) -
Utc
:UTC时间 -
Unspecified
:不指定
Calendar
:日历,使用哪个国家的日历,一般在Unity开发中不使用
年、月、日、时、分、秒、毫秒
1 | print(dt.Year + "-" + dt.Month + "-" + dt.Day + ": " + dt.Hour + ":" + dt.Minute + ":" + dt.Second + ":" + dt.Millisecond); |
tick表示
以格里高利历00:00:00.000年1月1日以来的100纳秒间隔数表示,一般是一个很大的数字
1 | print(dt.Ticks); //输出:638344714805000000 |
一年的第几天
1 | print(dt.DayOfYear); //输出:305 |
星期几
1 | print(dt.DayOfWeek); //输出:Wednesday |
获取时间
-
当前日期和时间
注意:不要在帧更新函数中不停地用
DateTime.Now
来计算,浪费性能。我们只需要在面板打开时计算一次时间差!之后再用该时间差来计算即可1
2DateTime nowTime = DateTime.Now;
print(nowTime.Year + "-" + nowTime.Month + "-" + nowTime.Day + ": " + nowTime.Hour + ":" + nowTime.Minute + ":" + nowTime.Second); -
返回今日日期
1
2DateTime nowTime2 = DateTime.Today;
print(nowTime2.Year + "-" + nowTime2.Month + "-" + nowTime2.Day); -
返回当前UTC日期和时间
1
2DateTime nowTimeUTC = DateTime.UtcNow;
print(nowTimeUTC.Hour + ":" + nowTimeUTC.Minute);
计算时间
就是很简单的各种加时间
1 | DateTime nowTime3 = nowTime.AddDays(1); //加一天 |
DateTime的字符串输出
1 | //格式:月/日/年 时:分:秒 |
通过传入参数来决定输出格式
1 | //传入参数,以使用特定的格式来输出字符串 |
字符串转DateTime
字符串想要转回 DateTime
成功的话,那么这个字符串的格式是有要求的,
一定是最基本的 toString()
的转换出来的字符串才能转回去(即一定要 dateTime.ToString()
转出来的形式,不能带任何参数)
要求格式:年/月/日 时:分:秒
1 | string str = nowTime.ToString(); |
存储时间
存储时间 方式很多
- 以直接存字符串
- 可以直接存Ticks
- 可以直接存时间戳信息
建议直接用存储时间戳的形式 更加节约,但存储时间戳需要用 TimeSpan
的类
TimeSpan
命名空间:System
TimeSpan
是 C# 提供给我们的时间跨度结构体,用两个 DateTime
对象相减 可以得到该对象
1 | //时间戳 |
初始化它来代表时间间隔
1 | TimeSpan ts2 = new TimeSpan(1, 2, 1, 0); //天数,小时,分钟,秒 |
TimeSpan相互计算
1 | TimeSpan ts3 = new TimeSpan(0, 1, 1, 1); |
TimeSpan常量方便用于和ticks进行计算
1 | print(ts4.Ticks / TimeSpan.TicksPerSecond); //将tick数转换为秒数 |
DateTime和Timespan的应用
假设要记录 以当前系统时间起,间隔2天后的 时间戳信息
获取并存储时间戳
1 | //用当前时间加上两天,再减去UNIX TIME纪元时间,得到时间差 |
将时间戳转换为DateTime
1 | //由于时间戳以秒为单位存储,我们需要先将时间戳转换为以ticks为单位的TimeSpan,得到较UNIX TIME纪元时间的时间差 |
计算倒计时
每次打开面板时计算目标时间与当前时间的秒数差,在面板中对显示内容进行更新
注意:不要在帧更新函数中不停用
DateTime.Now
来计算,浪费性能。我们只需要在面板打开时计算一次时间差!之后再用该时间差来计算即可
1 | int remainingSeconds = (int)(date - DateTime.Now).TotalSeconds; |