Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将字符串转换为GregorianCalendar_Java_Calendar_Timezone - Fatal编程技术网

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();这个问题的现代答案早就应该给出了。谢谢你提供它!