我正在使用Java 6.我们的服务器在东部标准时间(GMT-5),我正在尝试存储一个应该被解释为这样的值,但我对如何转换它感到困惑。我有
String dateStr = "1368921600000"; // This is 5/19/2013 00:00:00
final Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("GMT-5"));
cal.setTimeInMillis(Long.parseLong(dateStr));
final java.util.Date dateObj = cal.getTime();
System.out.println(dateObj.toString());
但是现在这打印出“5月18日星期六19:00:00 CDT 2013”(因为我的本地机器在CDT上)但是我希望结果是“Sat May 18 24:00:00 CDT 2013”。如何将日期字符串“1368921600000”解释为EST日期?谢谢, - 戴夫
答案 0 :(得分:2)
1368921600000
是一个瞬间,同一时刻,世界各地。要将其转换为日期和时间,您必须在世界中指定 where ,以了解 instant 的日期/时间。事实上,时间戳是相对于UTC的,并且 Sun,2013年5月19日00:00:00 GMT 。
如果你想在世界其他地方的这个瞬间(同一时刻)的时间,你可以像你一样使用日历并提取单个字段值(例如HOUR_OF_DAY)。如果您只关心获取文本字符串,则使用DateFormat实例,例如SimpleDateFormat:
DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z");
df.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String timeOnUSEastCoast = df.format(new Date(1368921600000L));
// will be GMT-5 or GMT-4 depending on DST
在这个例子中,输出将是GMT-4:星期六,2013年5月18日20:00:00美国东部时间(不仅时间已经改变,但它仍然是前一天在美国东海岸。)
如果你想输出UTC时间但只是想假装它的EST那么就更容易告诉DateFormat在文本中省略时区字段(删除“z”)输出并随意调用它,但要了解时间戳值始终为UTC。
答案 1 :(得分:1)
通常没有必要使用Joda Time库来获得历史上准确的时区和日光节省感知的本地时间映射,尽管这是许多人常见的响应。
如果你有一个需要本地时间转换的时间戳数据库,那么这里有一些很好的原则:
以UTC时间存储日期/时间(用Joda说明的Instants;用Java Calendar API说明的日期)。 UTC不关心DST。它不关心时区。 UTC简单地代表了一个具有普遍代表性的时刻。仅此步骤可以节省大量日期/时间的麻烦。
数据库记录应包含TimeZone和/或Locale字段,以便可以执行UTC的映射。想想你的数据。数据库中的每个时间戳都不需要与之关联的时区信息。而是将时区数据与提供适当粒度的数据模型的一部分相关联。如果您的应用只会在一个时区进行本地化,那么您根本不需要存储此信息。在我最近的项目中,我创建了一个Locale表,其中包含我的Encounters表中时间戳的TZ ID。所有其他时间戳都从属于这些记录,因此将其关联在那里是有意义的。
使用Java API GregorianCalendar将UTC日期映射到本地时间。这就是我用过的所有东西。我几乎从不使用GregorianCalendars进行日期算术或其他日期操作。以下是我一直在使用的范例:
public static void main(String[] args) {
m_GregorianCalendar = new GregorianCalendar(TimeZone.getTimeZone(
"America/Chicago"));
Date d = new Date();
String fmt = "dd-MMM-yyyy @ HH:mm";
:
:
String myDate = mapToLocalTime(d, fmt, gc);
:
:
}
public String mapToLocalTime(Date utc, String format, GregorianCalendar gc) {
gc.setTime(utc); // this calendar is already timezone aware (constructed
// with time zone id (DST too))
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.setCalendar(gc); // formatter uses conventions of calendar
sdf.applyPattern(fmt); // pattern for formatter
return sdf.format(utc);
}
考虑以数字格式(longs,double)在内部表示时间戳。这大大简化了日期比较和日期算术。唯一的缺点是必须进行转换才能将数据格式化为人类可识别的形式,但如果您使用函数进行这些转换,则根本不需要做大事。
答案 2 :(得分:0)
使用new java.util.SimpleDateFormat(format)
或java.util.DateFormat.getDateTimeInstance(int,int)
,然后使用#setTimeZone(timezone)
。
答案 3 :(得分:0)
当您打印Date.toString()时,根本不考虑日历的时区。执行cal.getTime()后,在Calendar中设置的内容不再相关。
TimeZone的默认时区是什么。
因此,在打印日期之前,将默认时区设置为您要打印的时区,例如:
String dateStr = "1368921600000"; // This is 5/19/2013 00:00:00
final Calendar cal = Calendar.getInstance();
TimeZone gmtZero = TimeZone.getTimeZone("GMT");
cal.setTimeInMillis(Long.parseLong(dateStr));
final java.util.Date dateObj = cal.getTime();
TimeZone.setDefault(gmtZero);
System.out.println(dateObj.toString());
无论您的系统时区如何,都会以GMT格式打印日期。
请记住之后恢复原来的默认TimeZone!