我最近用jconsole监控了我的Java程序。我将 CPU 使用率数据保存为 csv 文件。这就是我得到的:
Time,CPU Usage
43690.008014,1,8
43690.008060,0,1
43690.008106,0,1
43690.008153,0,1
43690.008199,0,1
43690.008245,0,1
CPU Usage
列很清楚,但我不能对Time
列说同样的话。什么是43690.008014
?如何将其解析为Date
?我一生中从未见过这样的事情。
CSV 文件中记录的持续时间是自1899-12-31
1以来的天数。为了获取当前日期,您可以将此持续时间添加到LocalDate.of(1899, 12, 30).atStartOfDay().atOffset(ZoneOffset.UTC)
.我建议您使用以 ISO-8601 标准为模型的java.time.Duration
,并在 JSR-310 实现中随Java-8一起引入。该函数Duration#ofNanos
为您提供一个表示指定纳秒数的Duration
。尽管已经有一个函数,但我建议您使用此函数的原因是,Duration#ofDays
这些函数将long
值作为参数,并且如果您在日志文件中强制转换持续时间(例如43690.008014
(long
,其小数部分将丢失,从而得到不正确的结果。
因此,将这些天转换为纳秒,从生成的纳秒中获取Duration
并将其添加到LocalDate.of(1899, 12, 30).atStartOfDay().atOffset(ZoneOffset.UTC)
以获取UTC
中的当前日期和时间。
演示:
import java.time.Duration;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class Main {
public static void main(String[] args) {
OffsetDateTime startDateTime = LocalDate.of(1899, 12, 30).atStartOfDay().atOffset(ZoneOffset.UTC);
OffsetDateTime current = startDateTime
.plus(Duration.ofNanos((long) (43690.008014 * 24 * 60 * 60 * 1000_000_000)));
System.out.println(current);
}
}
输出:
2019-08-13T00:11:32.409600512Z
从跟踪:日期时间中了解现代日期时间 API。
- 出于任何原因,如果你必须坚持使用 Java 6 或 Java 7,你可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。
- 如果您正在为 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请查看通过脱糖提供的 Java 8+ API 和如何在 Android Project 中使用 ThreeTenABP。
1 为什么 Access/SQL Server 中的 1899-12-30 是零日期,而不是 12/31?
时间格式为daysSinceEpoch.fractionOfCurrentDay
daysSinceEpoch
从 1899-12-30 开始,而不是 1900-01-01
fractionOfCurrentDay
是当天的百万分之一,范围从零到999999
(23:59:59(
您可以使用以下函数转换为本地日期时间:
public static LocalDateTime convert( final String jconsoleDateFormat )
{
String[] split = jconsoleDateFormat.split( "\." );
long daysSinceEpoch = Long.parseLong( split[0] );
long dayFraction = Long.parseLong( split[1] );
LocalDateTime epochDate = LocalDateTime.of( 1899,12,30, 0,0 );
LocalDateTime currentDate = epochDate.plusDays( daysSinceEpoch );
long secondsADay = 24 * 60 * 60L; // 86_400
long secondsSinceDayStarted = secondsADay * dayFraction / 1_000_000;
return currentDate.plusSeconds( secondsSinceDayStarted );
}
public static void main( String[] args )
{
System.out.println( convert( "43690.008014" ) ); // 2019-08-13T00:11:32
}