目录
一、TDateTime 时间格式
二、Unix/Linux的日期和时间格式
三、Delphi中操作Unix/Linux格式的日期和时间
1. TDateTime 转 Unix/Linux格式
2. Unix/Linux格式 转 TDateTime
3. 与腾讯、阿里等平台(简称:平台)时间转换
四、Delphi实现13位Unix/Linux格式时间函数
1. DateTimeToUnix13
2. UnixToDateTime13
附录、Windows 11 时区设置
1. 在右下角时间上右键单击,选择【调整日期和时间】
2. 选择调整时区
在Delphi中,表示时间用TDateTime类型,围绕TDateTime有很多相关的处理时间的函数,例如:获取当前时间的函数:now
TDateTime声明为double类型,含有日期-时间值。TDateTime值的整体部分是自1899年12月30日以来已经过去的天数。TDateTime值的小数部分是一天中的时间。TDateTime值支持的最大的正确日期被限制在12/31/9999 23:59:59:999。所有超过这个日期的值都会在大多数用TDateTime值操作的例程中引起错误和异常。
TDateTime也支持负值。应该小心使用负的TDateTime值。不正确地使用负值会导致各种问题。
下表显示了TDateTime值的例子和它们相应的日期和时间:
Value | Description(24H) |
0 | 1899-12-30 12:00:00 |
2.75 | 1900-01-01 18:00:00 |
-1.25 | 1899-12-29 06:00:00 |
35065 | 1966-01-01 12:00:00 |
DateUtils单元有几个API(如DaysBetween、HoursBetween、WeeksBetween等),它们是计算两个TDateTime之间的时间的更好的API,这些API无论底层的双数是负数还是正数都能工作。
当处理负的TDateTime值时,计算必须单独处理时间部分。小数部分反映了24小时内的时间,而不考虑TDateTime值的符号。例如,1899年12月29日上午6点是-1.25,而不是-1+0.25,这等于-0.75。大于-1.0到0.0的日期,和小于1.0到0.0的日期,是相互映照的(是同一天)。这是因为+0和-0是相等的。
在Delphi中,Unix的日期和时间值被编码为1970年1月1日开始的午夜后的秒数。但是在其他的语言或者系统中(例如javascript语言),Unix的日期和时间值也被编码为1970年1月1日开始的午夜后的毫秒数。
使用函数DateTimeToUnix(位于System.DateUtils单元中),调用DateTimeToUnix将一个TDateTime值转换为相同日期和时间的相应Unix/Linux编码。
//函数原型
function DateTimeToUnix(const AValue: TDateTime; AInputIsUTC: Boolean): Int64;
特别注意:
参数 AInputIsUTC 表示需要转换的 AValue 是不是UTC时间,默认值是True,表示是。具体UTC时间是什么,网上可以查询到,简单的理解就当时GMT+0时间,但是对于我们国家,我们一般使用的是GMT+8时间。这样就产生一个问题,AInputIsUTC不同的值,返回的结果将不一样!
对于Delphi中的now函数(返回当前时间),已经按照操作系统的时区调整了,也就是说表示的是操作系统选择的时区的时间。
例如:
T := 2023-04-08 1:19:53(TDateTime )
序号 | 函数 | 结果 | 说明 |
1 | DateTimeToUnix(T) | 1680916793 | UTC时间 |
2 | DateTimeToUnix(T,False) | 1680887993 | 当前时区时间(北京时间) |
以上结果相差8个小时!
使用函数UnixToDateTime(位于System.DateUtils单元中),调用UnixToDateTime将一个Unix/Linux编码值转换为相同日期和时间的相应TDateTime格式。
//函数原型
function UnixToDateTime(const AValue: Int64; AReturnUTC: Boolean): TDateTime;
特别注意:
参数AReturnUTC表示是否返回UTC时间,默认是True,如果需要返回当前时区时间,请将其设置位False。
例如:
T := 1680916793(Unix/Linux格式10位数字时间)
序号 | 函数 | 结果 | 说明 |
1 | UnixToDateTime(T) | 2023-04-08 1:19:53 | UTC时间 |
2 | UnixToDateTime(T,False) | 2023-04-08 9:19:53 | 当前时区时间(北京时间) |
以上结果相差8个小时!
如果以上说明还不是很明白,那么简单来说,如果需要和平台有时间签名的需求,一般平台要求的时间是Unix/Linux格式的UTC时间(GMT+0)。
Delphi用 now 函数取得当前时间,需要转换成平台要求的Unix/Linux格式时间,一定使用DateTimeToUnix(T,False)函数,也就是说一定要加参数False,否则Delphi会认为参数T就是UTC时间。很多开发的朋友只知道相差8个小时,但并不知道原因。
当平台返回一个Unix/Linux格式时间,我们需要在Delphi中使用,就一定要用UnixToDateTime(T,False)函数,也就是说一定要加参数False。这样转换过来的就是我们需要的当地时间(北京时间)。
有些朋友开发时,知道相差8个小时,然后通过IncHour(System.DateUtils单元中)函数增加或者减少8个小时,也达到了目的。实际上Delphi已经提供了参数控制是UTC时间还是当地时间。
因为平台要面对的是全球所有时区,所不能使用当地时间,只能使用UTC时间,因为UTC时间是一个,大家都是统一的!
Delphi官方只提供了10位精确到秒的转换函数,有时候我们也需要13位精确到毫秒的转换函数,下面两个函数精确到毫秒。
function DateTimeToUnix13(const AValue: TDateTime; AInputIsUTC: Boolean = True): Int64;
var
LDate: TDateTime;
begin
if AInputIsUTC then
LDate := AValue
else
LDate := TTimeZone.Local.ToUniversalTime(AValue);
Result := MilliSecondsBetween(UnixDateDelta, LDate);
if LDate < UnixDateDelta then //{UnixDateDelta = $63E1,1970-01-01}
Result := -Result;
end;
function UnixToDateTime13(const AValue: Int64; AReturnUTC: Boolean = True): TDateTime;
begin
if AReturnUTC then
Result := IncMilliSecond(UnixDateDelta, AValue)
else
Result := TTimeZone.Local.ToLocalTime(IncMilliSecond(UnixDateDelta, AValue));
end;
以上为自己学习总结,如果能帮到大家就开心了,如果