如何在Java中将currentTimeMillis转换为日期?


140

我在服务器中生成的某些日志文件中有毫秒,我也知道从中生成日志文件的语言环境,我的问题是将毫秒转换为指定格式的日期。该日志的处理在不同时区的服务器上进行。转换为“ 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

不要将Locale与时区混淆。完全分开。语言环境确定人的语言的名称,包括月份和日期的名称以及文化规范,例如部件的顺序(如月份,日期等)。时区与UTC偏移,加上处理异常的规则(如夏时制)。
罗勒·布尔克

毫秒数不是从1970-01-01T00:00:00Z开始而是从其他时刻开始计数的问题吗?
罗勒·布尔克

仅供参考,糟糕的旧日期时间类(GregorianCalendarSimpleDateFormat等)和出色的Joda-Time库现在都被现代的java.time类所取代。
罗勒·布尔克

Answers:


115
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);

我必须将Calendar设置为final才能使其正常工作。final Calendar calendar = Calendar.getInstance();
维克多·奥古斯托

4
通常认为日历对象很大,因此应尽可能避免使用。如果Date对象具有所需的功能,它将更好。“日期=新的日期(毫秒);” AVD用户在其他答案中提供的路线将是最佳途径:)
Dick Lucas

1
不知怎的,对1515436200000l,我得到calendar.get(Calendar.MONTH))0
萨吉布·阿查里亚

仅供参考,非常麻烦旧日期,时间类,如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat现在的遗产,由取代java.time内置到Java 8和更高等级。请参见Oracle 教程
罗勒·布尔克

2
@SajibAcharya注意Calendar.MONTH的实例从0开始;您需要添加一个来获得我们所知的“真实”月份。例如:0 = 1月,1 = 2月,2 = 3月,
依此类推

256

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

Date date=new Date(millis);

我们可以使用java.time包(教程)-Java SE 8中引入的DateTime API。

var instance = java.time.Instant.ofEpochMilli(millis);
var localDateTime = java.time.LocalDateTime
                        .ofInstant(instance, java.time.ZoneId.of("Asia/Kolkata"));
var zonedDateTime = java.time.ZonedDateTime
                            .ofInstant(instance,java.time.ZoneId.of("Asia/Kolkata"));

// Format the date

var formatter = java.time.format.DateTimeFormatter.ofPattern("u-M-d hh:mm:ss a O");
var string = zonedDateTime.format(formatter);

2
效率更高。
乍得宾厄姆

2
不。并非所有方法java.util.Date都已弃用。(JDK8中改进了日期和时间API java.time
adatapost

1
@RafaelZeffa,'''Date(long date)'''构造函数未弃用
Gugelhupf

提供Date对象是为了向后兼容。最好按照上面的建议使用日历。
Ton Snoei

2
仅供参考,非常麻烦旧日期,时间类,如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat现在的遗产,由取代java.time内置到Java 8和更高等级。请参见Oracle 教程
罗勒·布尔克

24

tl; dr

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和更高版本。许多功能都向后移植到Java 6和7,并进一步适用于Android。由与制作Joda-Time相同的人制作

一个Instant是在时间轴上的一个时刻UTC,分辨率为纳秒。它的时代是1970年UTC的第一时刻。

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

Instant instant = Instant.ofEpochMilli( 1_322_018_752_992L );

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

Z标准ISO 8601格式的字符串的缩写Zulu,表示UTC

使用正确的时区名称应用时区,以获取ZonedDateTime

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

看到此代码在IdeOne.com上实时运行

Asia/Kolkata 时区 ?

我猜您是在印度时区影响您的代码。我们在这里看到,调整到Asia/Kolkata时区会产生与您报告相同的一天中的时间,08:55这比我们的UTC值早五个半小时03:25

2011-11-23T08:55:52.992 + 05:30 [亚洲/加尔各答]

默认区域

您可以应用JVM 的当前默认时区。请注意,默认值可以在运行时随时更改。JVM中任何应用程序的任何线程中的任何代码都可以更改当前默认值。如果重要,请向用户询问所需/预期的时区。

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

关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

使用符合JDBC 4.2或更高版本的JDBC驱动程序,您可以直接与数据库交换java.time对象。不需要字符串或java.sql。*类。

在哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


将上面推荐的Instant转换为设备(例如,智能手机)上默认的本地时区是否容易?
AJW

1
@AJW是的。致电ZoneId.systemDefault()。请参阅“答案”末尾添加的新部分。
罗勒·布尔克

太好了,我会尝试的。
AJW

14

最简单的方法是使用Joda DateTime类,并指定时间戳(以毫秒为单位)和所需的DateTimeZone。

我强烈建议您避免使用内置的Java Date和Calendar类。他们太可怕了。


GorgianCalender无法正常工作...无论出于何种原因,它都占用了系统默认时区。乔达(Joda)表现出色。
阿米特

让我知道看看示例代码,是否可以使用Gregorian做一些不同的事情
Amit

1
仅供参考,Joda-Time项目现在处于维护模式,建议迁移到java.time类。请参见Oracle教程
罗勒·布尔克

13

如果按照JVM的标准,毫秒值是自格林尼治标准时间1970年1月1日以来的毫秒数,则该值与时区无关。如果要使用特定时区设置其格式,只需将其转换为GregorianCalendar对象并设置时区即可。之后,有许多方法可以格式化它。


1
这是GregorianCalendar和Joda的示例代码,我使用Joda获得了正确的输出,但是没有使用Gregorian GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone(“ US / Central”)));calendar.setTimeInMillis(yourmilliseconds); DateTime jodaTime =新的DateTime(yourmilliseconds,DateTimeZone.forTimeZone(TimeZone.getTimeZone(“ US / Central”)));; DateTimeFormatter parser1 = DateTimeFormat.forPattern(“ yyyy-MM-dd HH:mm:ss,SSS”);
阿米特

在日历对象中设置时区无效,但在日期格式程序对象中设置时区却有效?
条例草案

什么是DateTime和DateTimeFormatter?
SweetWisher 2013年

11

我的解决方案

public class CalendarUtils {

    public static String dateFormat = "dd-MM-yyyy hh:mm";
    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);

    public static String ConvertMilliSecondsToFormattedDate(String milliSeconds){
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(Long.parseLong(milliSeconds));
        return simpleDateFormat.format(calendar.getTime());
    }
}

6

我这样做是这样的:

static String formatDate(long dateInMillis) {
    Date date = new Date(dateInMillis);
    return DateFormat.getDateInstance().format(date);
}

您还可以使用getDateInstance(int style)以下参数:

DateFormat.SHORT

DateFormat.MEDIUM

DateFormat.LONG

DateFormat.FULL

DateFormat.DEFAULT




2

以下是我的解决方案,可将日期从毫秒转换为日期格式。您必须使用Joda Library才能运行此代码。

import java.util.GregorianCalendar;
import java.util.TimeZone;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class time {

    public static void main(String args[]){

        String str = "1431601084000";
        long geTime= Long.parseLong(str);
        GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("US/Central"));
        calendar.setTimeInMillis(geTime);
        DateTime jodaTime = new DateTime(geTime, 
               DateTimeZone.forTimeZone(TimeZone.getTimeZone("US/Central")));
        DateTimeFormatter parser1 = DateTimeFormat.forPattern("yyyy-MM-dd");
        System.out.println("Get Time : "+parser1.print(jodaTime));

   }
}

1

您可以尝试java.time api;

        Instant date = Instant.ofEpochMilli(1549362600000l);
        LocalDateTime utc = LocalDateTime.ofInstant(date, ZoneOffset.UTC);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.