我有以下代码进行一串毫秒(将来自RSS feed,因此将是一个字符串,下面的示例是快速测试程序),然后将这些毫里转换为日期对象。

public static void main(String[] args) {
    String ms = "1302805253";
    SimpleDateFormat dateFormatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(Long.parseLong(ms));

    try {
        String dateFormat = dateFormatter.format(calendar.getTime());
        System.out.println("Date Format = " + dateFormat);

        Date dateParse = dateFormatter.parse(dateFormatter.format(calendar.getTime()));
        System.out.println("Date Parse  = " + dateParse);
    } catch (ParseException e) {
        // TODO: handle exception
    }
}


Output:
    Date Format = Fri, 16 Jan 1970 02:53:25 GMT
    Date Parse  = Fri Jan 16 03:53:25 GMT 1970

如您所见,在日历对象的格式和结果字符串的解析之间,丢失了一个小时。同样,输出的格式已更改。谁能帮助我了解为什么会发生这种情况以及如何解决?我希望日期对象与“日期格式”输出的格式相同。

有帮助吗?

解决方案

我相信这是因为英国没有 实际上 1970年使用GMT,Java周围有一个错误...它将 格式 1970年的日期仿佛英国正在使用GMT,但没有真正改变偏移。简单示例:

Date date = new Date(0);
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss zzz");
sdf.setTimeZone(TimeZone.getTimeZone("Europe/London"));
System.out.println(sdf.format(date));

结果:

01 Jan 1970 01:00:00 GMT

请注意,它声称是GMT的凌晨1点...这是不正确的。它 曾是 在欧洲/伦敦时间上午1点,但欧洲/伦敦没有观察GMT。

乔达时间 正确地说,它打印出BST-但Joda Time不喜欢 解析 时区缩写的值。但是,您可以让它使用时区 OFFET 反而:

import org.joda.time.*;
import org.joda.time.format.*;

public class Test {
    public static void main(String[] args) throws Exception {
        DateTime date = new DateTime(0, DateTimeZone.forID("Europe/London"));

        DateTimeFormatter formatter = DateTimeFormat.forPattern(
            "dd MMM yyyy HH:mm:ss Z");

        String text = formatter.print(date); // 01 Jan 1970 01:00:00 +0100
        System.out.println(text);

        DateTime parsed = formatter.parseDateTime(text);
        System.out.println(parsed.equals(date)); // true
    }
}

其他提示

乔恩·斯基特(Jon Skeet)的回答 是正确的。

Java.Time

让我们通过Java进行相同的输入。时间以查看结果。

指定 适当的时区名称. 。切勿使用3-4个字母缩写 BST, EST, , 或者 IST 因为它们不是真正的时区,而不是标准化的,甚至不是唯一的(!)。所以我们使用 Europe/London.

Instant 班级代表时间表上的片刻 世界标准时间 分辨率 纳秒.

String input = "1302805253";
long millis = Long.parseLong ( input );
Instant instant = Instant.ofEpochMilli ( millis );

应用时区生产一个 ZonedDateTime 目的。

ZoneId zoneId = ZoneId.of ( "Europe/London" );
ZonedDateTime zdt = instant.atZone ( zoneId );

转储到控制台。我们确实看到了 Europe/London 那一刻比UTC提前一个小时。所以一天的时间是 02 小时而不是 01 小时。两者都代表时间表上同一时刻,只是通过两个不同的镜头观看 墙上的时间.

System.out.println ( "input: " + input + " | instant: " + instant + " | zdt: " + zdt );

输入:1302805253 |即时:1970-01-16T01:53:25.253Z | ZDT:1970-01-16T02:53:25.253+01:00 [欧洲/伦敦

全秒

顺便说一下,我怀疑您的输入字符串代表 所有的 自1970年UTC时代以来的几秒钟而不是 毫秒. 。该问题解释为,我们在2011年获得约会,这个问题发布。

String output = Instant.ofEpochSecond ( Long.parseLong ( "1302805253" ) ).atZone ( ZoneId.of ( "Europe/London" ) ).toString ();

2011-04-14T19:20:53+01:00 [欧洲/伦敦

关于Java.Time

Java.Time 框架内置在Java 8及以后的框架中。这些课程取代了旧的麻烦日期时间课,例如 java.util.Date, .Calendar, & java.text.SimpleDateFormat.

乔达时间 项目,现在 维护模式, ,建议迁移到Java.Time。

要了解更多,请参阅 Oracle教程. 。并搜索堆栈溢出以获取许多示例和解释。

java的大部分功能都将后输入到Java 6&7 in Threeten-Backport 并进一步适应 安卓三分.

Threeten-Extra 项目扩展Java.Time提供其他类。该项目是可能将来在Java.Time中增加的遗嘱。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top