【问题标题】:Calendar object in Java, returns wrong time?Java中的日历对象,返回错误的时间?
【发布时间】:2014-02-10 19:01:34
【问题描述】:

所以我一直在研究一个简单的小方法,它会将String 作为Calendar 对象返回。

这是我所拥有的:

Calendar cal = Calendar.getInstance();

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.ENGLISH);

try {
    cal.setTime(sdf.parse(this.getCreated_at()));
}
catch (ParseException e) {
    e.printStackTrace();
}

return cal;

现在假设从this.getCreated_at()) 获得的String 始终采用所需格式,理论上这应该可以完美运行。

只有一个小问题。

假设this.getCreated_at()) 返回Mon Feb 10 18:52:54 +0000 2014。应该不是问题吧?格式正确,一切都好。

但是,当我有我的主要方法时,请执行以下操作:

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");

System.out.println(sdf.format(... ... ....stringToCalendar().getTime())); 

它给了我以下输出:

ma feb 10 19:52:54 +0100 2014

您可能已经注意到,我的问题首先是时间不对。增加了一个小时。

其次,它将文本字段 Mon 和 Feb 翻译成 ma 和 feb,它们是挪威语的翻译,我现在正在编码的地方。

我需要将时间作为Calendar 对象返回给我,其方式与从this.getCreated_at())-string 中获得的完全相同。

我做错了什么?

谁能帮帮我?

顺便说一句,我来自挪威。那是 +01:00 标准偏移量。

【问题讨论】:

  • 您用于显示值的 SimpleDateFormat 采用默认(挪威)语言环境和时区,而不是英语。因此它使用挪威时区以挪威语显示日期。
  • @PavelHoral 已更新。那只是我有点太仓促的错字。请原谅。
  • 为什么您认为它显示的时间错误? 19:52:24 +01:00 在我看来完全正确 - 它与 18:52:24 +00:00 相同,但显示为您的时区。

标签: java string time calendar


【解决方案1】:

您可能已经注意到,我的问题首先是时间不对。增加了一个小时。

不,它没有。并不真地。它显示完全相同的时间,但在您当地的时区。不幸的是,您不能轻易确定原始时区,因为DateFormat.parse 返回一个Date,它不包含任何时区信息。 (在这种情况下,您实际上并不知道完整的时区 - 您只知道 UTC 偏移量,这并不完全相同。)

编辑:正如 Joni 的回答中所述,DateFormat.parse 确实保留了格式日历中的原始信息;您不需要时区,但可以使用存储在 Calendar 对象中的偏移量。就我个人而言,这似乎是一个我不想依赖的实现细节(尤其是当你最终得到一个偏移量时,同一个日历对象中的时区不一定支持!)但是你 如果你真的想要,可以把它弄坏。

其次,它将文本字段 Mon 和 Feb 翻译成 ma 和 feb 翻译成挪威语,即我现在编码的地方。

那是因为您的 SimpleDateFormat 使用的是您的默认语言环境。

你可以很容易地修复这部分:

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy",
    Locale.ENGLISH);

如果您知道要使用哪个时区,您也可以在SimpleDateFormat 上指定。否则,你会遇到一些困难。

我建议您改为使用Joda Time。这样,您可以将值解析为DateTime,它“知道”它所在的时区 - 因此您可以根据需要重新格式化它,同时保留相关的时区信息。

Joda 时间码示例:

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

class Test {
    public static void main(String[] args) {        
        DateTimeFormatter format = DateTimeFormat
            .forPattern("EEE MMM dd HH:mm:ss Z yyyy")
            .withLocale(Locale.ENGLISH);

        String input = "Mon Feb 10 18:52:54 +0000 2014";

        DateTime value = format.parseDateTime(input);
        System.out.println(format.print(value));
    }
}

【讨论】:

  • 您的回答最有帮助,我确实认为 Joda Time 看起来很有吸引力。您能否在回答中告诉我,我将如何在我的方法中使用它?如果我听起来很挑剔,那不是我的本意。你的回答真的很有用!
  • @ViRALiC:查看我的编辑...我只是在编写示例 :)
  • 啊,我明白了。然后我可以将DateTime 对象值转换为Calendar 对象,然后将其返回吗?还是我的问题会随之而来?我不想让你负担更多,但我的方法确实需要返回一个Calendar 对象。
  • @ViRALiC:您可以将其转换为Calendar(甚至还有toCalendar 方法),但您最好将一切都转换为 尽可能使用 Joda Time。
  • 如果只是为了满足我的好奇心,我想请你告诉我如何将它转换为 Calendar 对象。但是你已经帮了我很多,所以即使你应该选择不演示,你的回答也绝对被接受!
【解决方案2】:

您可以从日期格式中获取Calendar 实例:

sdf.parse(this.getCreated_at());
Calendar parsed = sdf.getCalendar();

此实例的字段设置为解析的内容:UTC 时区、时间 18:52:54 等...

不幸的是,似乎无法使用SimpleDateFormat 格式化Calendar 保存的值。

【讨论】:

  • 不,它没有。解析不会更改格式中的日历。 (我刚刚对此进行了测试。)
  • 当然是 Jon,that's how SimpleDateFormat works。我想看看你是怎么检查的,我知道你不会犯这样的错误。
  • 我很抱歉 - 它确实改变了日历中的 一些 字段。它确实不改变时区。尝试用“+0800”解析一个值,打印出前后日历中的时区——你会发现它没有改变。 (至少,我之后仍然说“欧洲/伦敦”,并且 8 小时的偏移量对于欧洲/伦敦肯定 not 有效。)如果你只是格式化你使用相同的格式化程序解析的值,它不会(必然)返回相同的结果 - 正是因为解析不会改变时区。
  • 您可以使用calendar.get(Calendar.ZONE_OFFSET) 获得偏移量,但这对我来说仍然是一个实现细节——您能否指出任何声明日历已填充在此的文档方式?
  • "此解析操作使用日历来生成日期。因此,日历的日期时间字段和 TimeZone 值可能已被覆盖,具体取决于子类实现。之前已通过调用 setTimeZone 设置的可能需要恢复以进行进一步操作。” docs.oracle.com/javase/7/docs/api/java/text/…(知道它必须在某个地方......)
猜你喜欢
  • 1970-01-01
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多