首先明白几个概念:
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;
本文来自博客园,作者:del88,转载请注明原文链接:https://www.cnblogs.com/del88/p/17414285.html