【问题标题】:Convert milliseconds to TDateTime in Java在 Java 中将毫秒转换为 TDateTime
【发布时间】:2013-09-18 18:59:07
【问题描述】:

我在一个需要保存TDateTime 类型(Delphi) 的文件的Android 项目中。我的日期以毫秒为单位,但我不知道如何将毫秒转换为 TDateTime

我有这样的事情:

Date dateInMillis = new Date(System.currentTimeMillis());
double dateInDouble = ???;

如果有任何提示可以帮助我解决这个问题,我会很高兴。

【问题讨论】:

  • 使用java Datetime函数将毫秒转换为日期时间

标签: java android delphi


【解决方案1】:

Delphi 的TDateTime 以天为单位测量时间。 Java 遵循 Unix 标准并以毫秒为单位进行测量。要在两者之间进行转换,您需要按一天中的毫秒数进行缩放,86400000

另一个区别是两个系统使用不同的时代。 Java 使用的 Unix 纪元是 1970 年 1 月 1 日 00:00。Delphi 纪元是 1899 年 12 月 30 日 00:00。以 Delphi TDateTime 表示的 Unix 纪元是 25569

因此,要将 Unix 纪元的毫秒转换为 Delphi 纪元的天数,请执行以下计算:

double delphiDateTime = unixMillis/86400000.0 + 25569.0;

【讨论】:

  • 这就是我几分钟前所做的!我需要等待 8 小时来回答我自己的问题,但这正是我所做的!谢谢大卫
【解决方案2】:

最近发布了带有新日期时间类的 Java 8,以下应该可以工作:

LocalDateTime localDateTime = LocalDateTime.of(1899, 12, 30, 0, 0);//Delphi date EPOCH time start
double fraction = val % 1;
long intPart = (long) (val - fraction);
localDateTime = localDateTime.plus(intPart, ChronoUnit.DAYS);
localDateTime = localDateTime.plus((long) (24*60*60*1000 * fraction), ChronoUnit.MILLIS); //fraction is a fraction of the time of day

【讨论】:

    【解决方案3】:

    tl;博士

    使用几年前取代 Date 类的现代 java.time 类。

    Duration duration =
            Duration.between(
                    LocalDate.of( 1899 , Month.DECEMBER , 30 ).atStartOfDay( ZoneOffset.UTC ).toInstant() ,  // Epoch reference moment used by Delphi.
                    Instant.now()  // Current moment as seen in UTC.
            );
    double temp =
            // Get a whole number of days (integer ) + a decimal fraction of partial day = a `double` number = the `TDateTime` type in Delphi.
            duration.toDays() +
                    (
                            ( double ) duration.minusDays( duration.toDays() ).toMillis()     // Milliseconds in our partial day.
                                    /
                                    ( double ) Duration.ofDays( 1 ).toMillis()                // Milliseconds in a full day, a generic 24-hour day.
                    );
    double r = Math.floor( temp * 1000 ) / 1000;  // Truncate to third decimal place to represent a resolution of milliseconds, the limit of `TDateTime` type in Delphi.
    

    java.time

    仅使用 Java 中的现代 java.time 类,切勿使用诸如 java.util.Datejava.sql.Date 之类的旧类。

    以 UTC 格式捕捉当前时刻。

    Instant now = Instant.now() ;  
    

    由于一些twisted history,因为它的epoch reference 为它的TDateTime 类Delphi 使用1899-12-30 的第一时刻大概在UTC。对于日期部分,请使用LocalDate

    LocalDate delphiEpochDate = LocalDate.of( 1899 , Month.DECEMBER , 30 ); // No, not the 31st, the 30th.
    

    epochDate.toString(): 1899-12-30

    作为一种习惯,让 java.time 确定一天中的第一个时刻,因为在所有区域中的所有日期并不总是 00:00。

    Instant delphiEpochMoment = delphiEpochDate.atStartOfDay( ZoneOffset.UTC ).toInstant();
    

    odt.toString(): 1899-12-30T00:00Z

    Delphi 使用一种从电子表格继承而来的糟糕的时间跟踪方法:使用double 浮点小数。

    整数部分代表全天,一般 24 小时长的一天,忽略政治时间的异常情况。对于这样的经过时间,我们使用Duration

    Duration d = Duration.between( delphiEpochMoment , now ) ;
    long days = d.toDays() ;  // Generic 24-hour long days.
    

    接下来,获取代表一天 24 小时的一部分的小数部分。首先,我们减去全天的数量,得到部分天数。

    Duration partialDay = d.minusDays( days ) ;
    

    然后将部分金额除以一整天的长度。我们将使用毫秒的分辨率,而不是 Duration 的纳秒能力,因为 Delphi 似乎仅限于毫秒。

    double millisOfPartialDay = partialDay.toMillis() ;
    double millisOfFullDay = Duration.ofDays( 1 ).toMillis() ;
    double tempResult = ( millisOfPartialDay / millisOfFullDay ) ;
    

    我们应该将结果截断到毫秒。要截断double,请参阅this Answer。我们应该加上我们的整数天数。

    double tempResult = days + ( millisOfPartialDay / millisOfFullDay ) ;
    double result = Math.floor( tempResult * 1000 ) / 1000 ;
    

    将所有内容放在一起。

    Instant now = Instant.now();
    
    LocalDate delphiEpochDate = LocalDate.of( 1899 , Month.DECEMBER , 30 ); // No, not the 31st, the 30th.
    Instant delphiEpochMoment = delphiEpochDate.atStartOfDay( ZoneOffset.UTC ).toInstant();
    
    Duration d = Duration.between( delphiEpochMoment , now );
    long days = d.toDays();  // Generic 24-hour long days.
    
    Duration partialDay = d.minusDays( days );
    
    double millisOfPartialDay = partialDay.toMillis();
    double millisOfFullDay = Duration.ofDays( 1 ).toMillis();
    
    double tempResult = days + ( millisOfPartialDay / millisOfFullDay );
    double result = Math.floor( tempResult * 1000 ) / 1000;  // Truncate to third decimal place to represent a resolution of milliseconds.
    
    System.out.println( "delphiEpochMoment = " + delphiEpochMoment );
    System.out.println( "d = " + d );
    System.out.println( "tempResult = " + tempResult );
    System.out.println( "result = " + result );
    

    delphiEpochMoment = 1899-12-30T00:00:00Z

    d = PT1056815H56M10.613011S

    tempResult = 44033.99734505787

    结果 = 44033.997

    警告:我没有测试过这段代码。而且我不使用Delphi。所以买家要小心:这个代码值得你付出的每一分钱。

    避免LocalDateTime

    注意:不要不要使用LocalDateTime 来表示片刻。此类表示具有时间的日期,但缺少时区或从 UTC 偏移的上下文。例如,取 2021 年 1 月 23 日中午的值。那会是日本东京的中午吗?还是法国图卢兹的中午?还是在美国俄亥俄州托莱多的中午?那将是三个非常不同的时刻,相隔几个小时。如果缺少时区,我们不知道是哪一个。

    在 Delphi 时间跟踪的这个特定问题中,您可以避开 LocalDateTime,因为 Delphi(大概)使用 UTC,而 UTC 和 LocalDateTime 一样使用通用的 24 小时天数。但是使用LocalDateTime 从概念上讲不适合这个问题,因为我们需要这里的时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-11
      • 1970-01-01
      • 2019-09-02
      • 1970-01-01
      • 2014-03-18
      相关资源
      最近更新 更多