Java 将字符串转换为GregorianCalendar
我有一个来自电子邮件标题的字符串,比如Java 将字符串转换为GregorianCalendar,java,calendar,timezone,Java,Calendar,Timezone,我有一个来自电子邮件标题的字符串,比如日期:Mon,Oct 2008 08:33:29-0700。我需要的是GregorianCalendar的一个实例,它将代表同一时刻。这么简单,我该怎么做 对于速度最快的,这是无法正常工作的: SimpleDateFormat format = ... // whatever you want Date date = format.parse(myString) GregorianCalendar calendar = new GregorianCalend
日期:Mon,Oct 2008 08:33:29-0700
。我需要的是GregorianCalendar的一个实例,它将代表同一时刻。这么简单,我该怎么做
对于速度最快的,这是无法正常工作的:
SimpleDateFormat format = ... // whatever you want
Date date = format.parse(myString)
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(date)
因为它会将时区标准化为UTC(或本地机器时间,取决于Java版本)。我需要的是calendar.getTimeZone().getRawOffset()来返回
-7*milisInAnHour
如果可以的话,我建议查看Joda时间库。当核心平台提供类似的功能时,我通常反对使用第三方库,但我例外,因为Joda Time的作者也支持JSR310,Joda Time最终基本上将被应用到Java 7中
因此,无论如何,如果Joda Time是一个选项,那么类似这样的东西应该会起作用:
我希望这有帮助
对于速度最快的人来说,这不会正常工作。。。
因为它会将时区标准化为UTC(或本地机器时间,取决于Java版本)。我需要的是calendar.getTimeZone().getRawOffset()返回-7*百万小时
从技术上讲,这是可行的,因为虽然它将返回一个时区等于当前系统时区的对象,但时间将被修改以考虑偏移量
此代码:
String dateString = "Mon, 27 Oct 2008 08:33:29 -0700";
DateFormat df = new SimpleDateFormat("E, dd MMM yyyy hh:mm:ss Z");
Date parsed = df.parse(dateString);
System.out.println("parsed date: " + parsed);
Calendar newCalendar = Calendar.getInstance();
newCalendar.setTime(parsed);
产出:
解析日期:2008年10月27日星期一11:33:29美国东部夏令时
这在技术上是正确的,因为我的系统时区是EDT/UTC减去四个小时(比你的时区早三个小时)。如果将时间表示为自1970年1月1日00:00:00 GMT(这是Date
对象存储其日期/时间的方式)以来的毫秒数,那么这些日期/时间是相等的,只是时区不同
你的问题是如何将日期/日历转换为时区?为此,请看一下我对上一个问题的回答java.time
使用java.time
的解决方案:
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "Mon, 27 Oct 2008 08:33:29 -0700";
OffsetDateTime odt = OffsetDateTime.parse(strDateTime, DateTimeFormatter.RFC_1123_DATE_TIME);
System.out.println(odt);
// In case you want a time zone neutral object, convert to Instant
Instant instant = odt.toInstant();
System.out.println(instant);
// Edit: If the requirement is a GregorianCalendar having the offset from
// the string — typically for an old API not yet upgraded to java.time:
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, DateTimeFormatter.RFC_1123_DATE_TIME);
GregorianCalendar gc = GregorianCalendar.from(zdt);
System.out.println("As Date: " + gc.getTime());
System.out.println("Time zone ID: " + gc.getTimeZone().getID());
System.out.println("Hour of day: " + gc.get(Calendar.HOUR_OF_DAY));
// ...
}
}
2008-10-27T08:33:29-07:00
2008-10-27T15:33:29Z
As Date: Mon Oct 27 15:33:29 GMT 2008
Time zone ID: GMT-07:00
Hour of day: 8
现代日期时间API提供了用时区偏移表示日期时间对象的功能。它可以转换为表示时间线上瞬时点的。即时
独立于任何时区,即其时区偏移量为+00:00
小时,在标准中指定为Z
将此瞬间转换为从1970-01-01T00:00:00Z开始的毫秒数。可以将该值设置为gregoriacalendar
的对象,然后该对象将表示相同的时刻
演示:
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "Mon, 27 Oct 2008 08:33:29 -0700";
OffsetDateTime odt = OffsetDateTime.parse(strDateTime, DateTimeFormatter.RFC_1123_DATE_TIME);
System.out.println(odt);
// In case you want a time zone neutral object, convert to Instant
Instant instant = odt.toInstant();
System.out.println(instant);
// Edit: If the requirement is a GregorianCalendar having the offset from
// the string — typically for an old API not yet upgraded to java.time:
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, DateTimeFormatter.RFC_1123_DATE_TIME);
GregorianCalendar gc = GregorianCalendar.from(zdt);
System.out.println("As Date: " + gc.getTime());
System.out.println("Time zone ID: " + gc.getTimeZone().getID());
System.out.println("Hour of day: " + gc.get(Calendar.HOUR_OF_DAY));
// ...
}
}
2008-10-27T08:33:29-07:00
2008-10-27T15:33:29Z
As Date: Mon Oct 27 15:33:29 GMT 2008
Time zone ID: GMT-07:00
Hour of day: 8
输出:
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "Mon, 27 Oct 2008 08:33:29 -0700";
OffsetDateTime odt = OffsetDateTime.parse(strDateTime, DateTimeFormatter.RFC_1123_DATE_TIME);
System.out.println(odt);
// In case you want a time zone neutral object, convert to Instant
Instant instant = odt.toInstant();
System.out.println(instant);
// Edit: If the requirement is a GregorianCalendar having the offset from
// the string — typically for an old API not yet upgraded to java.time:
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, DateTimeFormatter.RFC_1123_DATE_TIME);
GregorianCalendar gc = GregorianCalendar.from(zdt);
System.out.println("As Date: " + gc.getTime());
System.out.println("Time zone ID: " + gc.getTimeZone().getID());
System.out.println("Hour of day: " + gc.get(Calendar.HOUR_OF_DAY));
// ...
}
}
2008-10-27T08:33:29-07:00
2008-10-27T15:33:29Z
As Date: Mon Oct 27 15:33:29 GMT 2008
Time zone ID: GMT-07:00
Hour of day: 8
在GregoriaCalendar
上调用getTime()
会转换为一个没有时区的Date
(另一个旧的、容易出错的类),因此偏移量会丢失。打印时区ID和一天中的小时表明偏移量和一天中的时间都保留在GregoriaCalendar
中
从了解有关现代日期时间API的更多信息
*无论出于何种原因,如果您必须坚持使用Java6或Java7,您可以使用哪个backport将大部分Java.time功能移植到Java6&7。如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请检查并确认。
Minor旁白:您应该使用Calendar.getInstance()而不是直接实例化GregoriaCalendar。这仍然是灵活的,这样当你的应用程序在印度运行时,你就不必更改所有代码了(例如)。@Daniel:不一定。这取决于在印度运行的应用程序是否与印度人、ISO日期格式、其他未本地化的进程交互,或者您有什么。虽然我同意您应该使用Calendar.getInstance(并且您应该使用通用类型Calendar,而不是GregorianCalendar)。。。getInstance()仅在您的语言/国家为泰国/泰国时返回非GregorianCalendar!如果您正在做任何与日期和时间操作有关的远程复杂操作,而且听起来像是这样,我也强烈推荐Joda时间库。这是我见过的设计和实现最好的库之一,它使日期/时间处理尽可能简单(但不简单)!它只有一个bug,这是正确的一行。更新,我会接受的。DateTimeFormat.forPattern(“您的模式”).withOffsetParsed();这个问题的现代答案早就应该给出了。谢谢你提供它!