问题
我在服务器中生成的某个日志文件中有毫秒数,我也知道生成日志文件的区域设置,我的问题是将指定格式的毫秒转换为日期。该日志的处理发生在位于不同时区的服务器上。转换为"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.Date
class,然后使用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 );
##亚洲/加尔各答时区?
我猜你的印度时区正在影响你的代码。我们在这里看到调整到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
,Calendar
和SimpleDateFormat
。
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
,YearQuarter
和more。