Delphi 彻底搞懂 Unix/Linux 时间格式及平台间转换

目录

一、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. 选择调整时区


一、TDateTime 时间格式 

        在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是相等的。

二、Unix/Linux的日期和时间格式

        在Delphi中,Unix的日期和时间值被编码为1970年1月1日开始的午夜后的秒数。但是在其他的语言或者系统中(例如javascript语言),Unix的日期和时间值也被编码为1970年1月1日开始的午夜后的毫秒数

  1. 如果是秒数,则表示出的是一个10位整数,例如:1680864084 表示的是 2023-04-07 18:41:24
  2. 如果是毫秒数,则表示出的是一个13位的整数,因为1秒是1000毫秒。例如:1680864084583 表示的是 2023-04-07 18:41:24 583 (注意:后面多了3位数字583就表示的是583毫秒)。

三、Delphi中操作Unix/Linux格式的日期和时间

1.  TDateTime 转 Unix/Linux格式

        使用函数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个小时!

2. Unix/Linux格式 转 TDateTime

        使用函数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个小时!

3. 与腾讯、阿里等平台(简称:平台)时间转换

        如果以上说明还不是很明白,那么简单来说,如果需要和平台有时间签名的需求,一般平台要求的时间是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实现13位Unix/Linux格式时间函数

        Delphi官方只提供了10位精确到秒的转换函数,有时候我们也需要13位精确到毫秒的转换函数,下面两个函数精确到毫秒。

1.  DateTimeToUnix13

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;

2.  UnixToDateTime13    

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;

  

附录、Windows 11 时区设置

1.  在右下角时间上右键单击,选择【调整日期和时间】

 2. 选择调整时区

以上为自己学习总结,如果能帮到大家就开心了,如果

猜你喜欢

转载自blog.csdn.net/sensor_WU/article/details/130008747