问题

我在服务器中生成的某个日志文件中有毫秒数,我也知道生成日志文件的区域设置,我的问题是将指定格式的毫秒转换为日期。该日志的处理发生在位于不同时区的服务器上。转换为"SimpleDateFormat"程序时,机器的日期是这样的,因为这样的格式化日期并不代表服务器的正确时间。有没有办法优雅地处理这个问题?

long yourmilliseconds = 1322018752992l;
        //1322018752992-Nov 22, 2011 9:25:52 PM 

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS",Locale.US);

GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("US/Central"));
calendar.setTimeInMillis(yourmilliseconds);

System.out.println("GregorianCalendar -"+sdf.format(calendar.getTime()));

DateTime jodaTime = new DateTime(yourmilliseconds, 
                    DateTimeZone.forTimeZone(TimeZone.getTimeZone("US/Central")));
DateTimeFormatter parser1 = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss,SSS");

System.out.println("jodaTime "+parser1.print(jodaTime));

输出:

Gregorian Calendar -2011-11-23 08:55:52,992
jodaTime 2011-11-22 21:25:52,992

#1 热门回答(228 赞)

你可以使用java.util.Dateclass,然后使用SimpleDateFormat格式化6Date

Date date=new Date(millis);

#2 热门回答(88 赞)

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeStamp);

int mYear = calendar.get(Calendar.YEAR);
int mMonth = calendar.get(Calendar.MONTH);
int mDay = calendar.get(Calendar.DAY_OF_MONTH);

#3 热门回答(15 赞)

#tl;博士

Instant.ofEpochMilli( 1_322_018_752_992L )     // Parse count of milliseconds-since-start-of-1970-UTC into an `Instant`.
       .atZone( ZoneId.of( "Africa/Tunis" ) )  // Assign a time zone to the `Instant` to produce a `ZonedDateTime` object.

细节

其他答案使用过时或不正确的类。

避免使用旧的日期时间类,例如java.util.Date/.Calendar。事实证明,它们设计糟糕,令人困惑,并且很麻烦。

#java.time

java.time框架内置于Java 8及更高版本中。许多功能是backported to Java 6 & 7和进一步的adapted to Android。由一些人制作的Joda-Time制作。

AnInstant是时间轴UTC的片刻,分辨率为nanoseconds。 Itsepoch是1970年UTC的第一个时刻。

假设你的输入数据是从1970-01-01T00:00:00Z(在问题中不清楚)的毫秒数,那么我们可以轻松地实例化aInstant

Instant instant = Instant.ofEpochMilli( 1_322_018_752_992L );

instant.toString():2011-11-23T03:25:52.992Z

标准ISO 8601格式化字符串中的Z缩写为Zulu,意思是UTC

使用aproper time zone name应用时区,获取aZonedDateTime

ZoneId zoneId = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( zoneId );

code run live at IdeOne.com

##亚洲/加尔各答时区?

我猜你的印度时区正在影响你的代码。我们在这里看到调整到Asia/Kolkata时区会呈现与你报告时相同的时间,08:55比我们的UTC值03:25提前了五个半小时。

2011-11-23T08:55:52.992 05:30 [Asia / Kolkata]

#默认区域

你可以应用JVM的current default time zone。请注意,默认情况下,运行时的任何时刻都可以更改。 JVM中任何应用程序的任何线程中的任何代码都可以更改当前默认值。如果重要,请询问用户所需/预期的时区。

ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

#关于java.time

thejava.time框架内置于Java 8及更高版本中。这些类取代了麻烦的oldlegacy日期时间类,如java.util.Date,CalendarSimpleDateFormat

TheJoda-Timeproject,现在在maintenance mode,建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程。并搜索Stack Overflow以获取许多示例和解释。规格是JSR 310

如果aJDBC driver符合JDBC 4.2或更高版本,则可以直接使用数据库exchangejava.timeobjects。不需要字符串或java.sql。*类。

从哪里获取java.time类?

  • Java SE 8,Java SE 9和更高版本的内置版本。带有捆绑实现的标准Java API的一部分。 Java 9增加了一些小功能和修复。
  • Java SE 6和Java SE 7许多java.time功能都被反向移植到ThreeTen-Backport中的Java 6和7。
  • Android更新版本的Android捆绑java.time类的实现。对于早期的Android,ThreeTenABP项目采用ThreeTen-Backport(如上所述)。请参见如何使用ThreeTenABP ....

ThreeTen-Extraproject使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。你可以在这里找到一些有用的类,如Interval,YearWeek,YearQuartermore


原文链接