首先明白几个概念:

1. 本初子午线:

要想定位,地球上的一个位置,需要南北向的 “经线”,和东西向的“纬线”,古人以“子”为正北,以“午”为正南,故地理上的经线,在我国又称为“子午线”;

0度经线,又称为“本初子午线”,理论上任何一条经线,都可以被定义为本初子午线,那么导致了各个国家都有自己的本初子午线,认为自己是地球中心,反正

地球是圆的,到底谁是中心,谁是0度,不好说;为统一标准,最终在1884年于美国华盛顿举行的国际本初子午线大会上,正式认定英国伦敦格林尼治子午线为

经度的起点,就是以伦敦为经度的中心,也是世界标准时区的起点,中时区.....可自行百度了解;百科:https://baike.baidu.com/item/%E6%9C%AC%E5%88%9D%E5%AD%90%E5%8D%88%E7%BA%BF/248147

2. 时区:

简单说明,地球是圆的,360度,一天是24个小时,把地球分为24个时区,360/24 = 15度,每个时区跨15度,每个时区时间相差一个小时,中国的领土跨了,东5、6、7、8、9共5个时区,北京是在东8区上,为了公共

方便我国是采用首都北京的时间,就是东8区的时间,其它国家估计一样;这样会导致 同样是早上8点,上海的太阳比西安的太阳出来的早,“另外记住:地球是由西向东,逆时针旋转的”

我们国家虽然采用了 统一的北京时间,但是与其它国家还是有时差,比如日本,不可能让日本采用北京时间,日本是在东9区上;看下图吧:

自然日界线、人为日界线(国际日期变更线)的概念 自己区搜索,他们有视频 讲解说的 比较清晰:

中时区,也称0时区,时间的计算方式是:东加西减去;

3. UNIX时间戳:

 

==============================================================================================================

好了,了解了以上 概念后,还需要了解一个重要的概念,这个概念是引起 网上 那么多人 迷惑的主因;导致网上出现那么多人有疑惑。

当前时间,什么是当前时间,分为:当前的北京时间、当前的伦敦时间;

同理:1970-01-01 00:00:00 这个是 那个时候的 伦敦时间,那个时候的 北京时间是 :1970-01-01 08:00:00;

那么当前时间 与 1970 那个时间的差的 毫秒数 是 多少呢,这里有4个值,如下:

A1:当前的北京时间;

A2:当前的伦敦时间;

B1:过去的北京 纪元时间,1970-01-01 08:00:00

B2: 过去的伦敦 纪元时间:1970-01-01 00:00:00

这4个值:A1 - B1 = A2 - B2 = 当前 - 过去 = 我们需要的那个毫秒数;

若是 A1 - B2 或 A2 - B1 则会出错;

================

记下来看下 程序语言的实现,先说下 Java 语言:

public class Test {
    public static void main(String[] args) throws ParseException {
        /*
         Java里 比较简单,直接获取 这个 我们需要的毫秒数,他内部自动,要么 A1 - B1, 要么A2 - B2;
         反正我们不用管,他们它内部 帮我们处理好了。
         如何证明 System.currentTimeMillis() 就是 A1 - B1 或 A2 - B2的值呢,这里我想不到方法
         证明就不证明了,我感觉Java这里不会有问题;
         */
        System.out.println("当前 - 过去 = " + System.currentTimeMillis() + " 毫秒");


        if(new Date().getTime() == System.currentTimeMillis()){
            System.out.println("yes 看来他俩相等");
        }
    }
}

Java的使用上,一般没有什么问题,处理的很好,接下来 看下 Delphi语言,如何获取 A1 - B1 的结果,然后让 Java语言的结果 与 Delphi语言的结果 相减,看下 差多少

Java 里 先运行 看下 System.currentTimeMillis()的值:
当前 - 过去 = 1684480221885 毫秒
yes 看来他俩相等

把 1684480221885 放到 Delphi里 与 Delphi 里的 对比:

 Delphi 里 不要忘记 引入 Use System.DateUtils 这个单元;

procedure TForm1.btn1Click(Sender: TObject);
var
  delphi,java: Int64;
begin
  delphi := DateTimeToUnix(Now(), False) * 1000; //Delphi 里的 System.currentTimeMillis()
  java := 1684480221885;
  mmo1.Lines.Add(delphi.ToString);
  mmo1.Lines.Add((delphi - java).ToString);
end;

最终得出答案:Java里的 System.currentTimeMillis() = Delphi 里的DateTimeToUnix(Now(), False) * 1000; 为什么 要 乘以1000 ,Delphi 这个是标准的Unix时间戳 是秒数,所以要乘以1000;一般我们都是用毫秒。

接下来 看下 Delphi 里的 这个方法:

function DateTimeToUnix(const AValue: TDateTime; AInputIsUTC: Boolean = True): Int64;
function UnixToDateTime(const AValue: Int64; AReturnUTC: Boolean = True): TDateTime;

UTC就是 标准的 中时区/0时区时间,就是伦敦时间;

 

 

接下来看下,给好 正确的时间戳,转化成 正确的北京时间:

 

procedure TForm1.btn1Click(Sender: TObject);
var
  delphi,java: Int64;
begin
  delphi := DateTimeToUnix(Now(), False) * 1000; //Delphi 里的 System.currentTimeMillis()
  java := 1684480221885;
  mmo1.Lines.Add(delphi.ToString);
  mmo1.Lines.Add((delphi - java).ToString);

  //接下来看下 时间戳转出来的日期
  mmo1.Lines.Add(FormatDateTime('yyyy-mm-dd hh:mm:ss',UnixToDateTime(java div 1000, true))); // 伦敦时间 慢8小时
  mmo1.Lines.Add(FormatDateTime('yyyy-mm-dd hh:mm:ss',UnixToDateTime(java div 1000, false))); //这个才是正确的北京时间
  mmo1.Lines.Add(FormatDateTime('yyyy-mm-dd hh:mm:ss',UnixToDateTime(java div 1000)));//默认第二个参数为True, 伦敦时间 慢8小时
end;

 

=======================================

总结:

1. Java里 获取Unix时间戳(毫秒):

System.currentTimeMillis();//Unix时间戳这个是毫秒

//根据时间戳,转成时间的方法是
Date date = new Date("时间戳“); 

2. Delphi 里 获取 标准的Unix时间戳(秒),若要毫秒就乘以1000:

DateTimeToUnix(Now(), False);//标准的Unix时间戳是秒
DateTimeToUnix(Now(), False) * 1000;//要毫秒的话,就乘以1000

//根据时间戳,转化成北京时间的方法是:
FormatDateTime('yyyy-mm-dd hh:mm:ss', UnixToDateTime('时间戳毫秒' div 1000, False)); //这里这里是False

 

通常其它语言Unix时间戳 都是毫秒,由于 Delphi是秒,不方便,且通常不要开发者 关注 UTC那个参数,所以可以把官方的改造一下,变成毫秒版:

官方的:

function DateTimeToUnix(const AValue: TDateTime; AInputIsUTC: Boolean): Int64;
var
  LDate: TDateTime;
 begin
  if AInputIsUTC then
    LDate := AValue
  else
    LDate := TTimeZone.Local.ToUniversalTime(AValue);
  Result := SecondsBetween(UnixDateDelta, LDate);
  if LDate < UnixDateDelta then
     Result := -Result;
 end;

function UnixToDateTime(const AValue: Int64; AReturnUTC: Boolean): TDateTime;
begin
  if AReturnUTC then
    Result := IncSecond(UnixDateDelta, AValue)
  else
    Result := TTimeZone.Local.ToLocalTime(IncSecond(UnixDateDelta, AValue));
end;

改造后:

//Ex的意思是扩展,类似微软的Api扩展,如Sleep SleepEx
function DateTimeToUnixEx(const AValue: TDateTime): Int64;
var
  LDate: TDateTime;
 begin
   LDate := TTimeZone.Local.ToUniversalTime(AValue);
   //这里SecondsBetween改成MilliSecondsBetween,由秒修改成毫秒
   Result := MilliSecondsBetween(UnixDateDelta, LDate);
   if LDate < UnixDateDelta then
     Result := -Result;
 end;

function UnixToDateTimeEx(const AValue: Int64): TDateTime;
begin
  //IncSecond 修改成IncMilliSecond
  Result := TTimeZone.Local.ToLocalTime(IncMilliSecond(UnixDateDelta, AValue));
end;

测试:

 

procedure TForm1.btn2Click(Sender: TObject);
var
  milli: Int64;
begin
  milli := DateTimeToUnixEx(Now()); //Delphi 里的 System.currentTimeMillis()
  mmo1.Lines.Add(milli.ToString);

  mmo1.Lines.Add(FormatDateTime('yyyy-mm-dd hh:mm:ss', UnixToDateTimeEx(milli)));
end;

 

posted on 2023-05-19 10:49  del88  阅读(11)  评论(0编辑  收藏  举报