Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.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 从字符串中提取时区对象的最佳方法?_Java_Timezone - Fatal编程技术网

Java 从字符串中提取时区对象的最佳方法?

Java 从字符串中提取时区对象的最佳方法?,java,timezone,Java,Timezone,我有一个数据库字段,其中包含一个原始日期字段(存储为字符数据),例如 2008年9月26日星期五东部夏令时晚上8:30 我可以使用SimpleDataFormat轻松地将其解析为日期 DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz"); Date scheduledDate = dbFormatter.parse(rawDate); 我想做的是从这个字符串中提取一个时区对象。此应用

我有一个数据库字段,其中包含一个原始日期字段(存储为字符数据),例如

2008年9月26日星期五东部夏令时晚上8:30

我可以使用SimpleDataFormat轻松地将其解析为日期

DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
Date scheduledDate = dbFormatter.parse(rawDate);
我想做的是从这个字符串中提取一个时区对象。此应用程序运行的JVM中的默认时区是GMT,因此我无法使用上面解析的
日期
中的
.getTimezoneOffset()
(因为它将返回默认时区)

除了标记原始字符串和查找时区字符串的起始位置(因为我知道格式总是
EEEE,MMMM dd,yyyy hh:mm aa zzzz
)是否有一种方法可以使用DateFormat/SimpleDataFormat/Date/Calendar API来提取时区对象,该对象将与我用
DateFormat.parse()解析的字符串具有相同的时区


Java API中的
Date
vs
Calendar
让我感到困扰的一点是
Calendar
应该在所有地方取代
Date
。。。但是后来他们决定,哦,嘿,让我们在
DateFormat
类中仍然使用
Date

作为一种局部解决方案,您可以使用正则表达式匹配来获取时区,因为它前面总是有相同的文本。上午或下午


我对Java时区的了解不足以让您了解它的最后一部分。

我发现:

        DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
        dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
        Date scheduledDate = dbFormatter.parse("Friday, September 26, 2008 8:30 PM Eastern Daylight Time");
        System.out.println(scheduledDate);
        System.out.println(dbFormatter.format(scheduledDate));
        TimeZone tz = dbFormatter.getTimeZone();
        System.out.println(tz.getDisplayName());
        dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
        System.out.println(dbFormatter.format(scheduledDate));
Fri Sep 26 20:30:00 CDT 2008
Friday, September 26, 2008 08:30 PM Eastern Standard Time
Eastern Standard Time
Friday, September 26, 2008 08:30 PM Central Daylight Time
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class TimeZoneExtracter {

    public static final void main(String[] args) throws ParseException {
        DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
        System.out.println(dbFormatter.getTimeZone());
        dbFormatter.parse("Fr, September 26, 2008 8:30 PM Eastern Daylight Time");
        System.out.println(dbFormatter.getTimeZone());
    }

}
产生以下结果:

        DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
        dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
        Date scheduledDate = dbFormatter.parse("Friday, September 26, 2008 8:30 PM Eastern Daylight Time");
        System.out.println(scheduledDate);
        System.out.println(dbFormatter.format(scheduledDate));
        TimeZone tz = dbFormatter.getTimeZone();
        System.out.println(tz.getDisplayName());
        dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
        System.out.println(dbFormatter.format(scheduledDate));
Fri Sep 26 20:30:00 CDT 2008
Friday, September 26, 2008 08:30 PM Eastern Standard Time
Eastern Standard Time
Friday, September 26, 2008 08:30 PM Central Daylight Time
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class TimeZoneExtracter {

    public static final void main(String[] args) throws ParseException {
        DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
        System.out.println(dbFormatter.getTimeZone());
        dbFormatter.parse("Fr, September 26, 2008 8:30 PM Eastern Daylight Time");
        System.out.println(dbFormatter.getTimeZone());
    }

}
事实上,我觉得这有点令人惊讶。但是,我想这表明,您的问题的答案是在解析之后,在格式化程序上调用getTimeZone

编辑:
以上是使用Sun的JDK1.6运行的

日期和日历的主要区别在于,日期只是一个值对象,没有修改它的方法。因此,它被设计用于在某处存储日期/时间信息。如果您使用日历对象,则可以在将其设置为使用日期/时间信息执行某些业务逻辑的持久实体后对其进行修改。这是非常危险的,因为实体无法识别此更改。 Calendar类是为日期/时间操作而设计的,比如添加天数之类的操作

根据您的示例,我得到以下结果:

        DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
        dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
        Date scheduledDate = dbFormatter.parse("Friday, September 26, 2008 8:30 PM Eastern Daylight Time");
        System.out.println(scheduledDate);
        System.out.println(dbFormatter.format(scheduledDate));
        TimeZone tz = dbFormatter.getTimeZone();
        System.out.println(tz.getDisplayName());
        dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
        System.out.println(dbFormatter.format(scheduledDate));
Fri Sep 26 20:30:00 CDT 2008
Friday, September 26, 2008 08:30 PM Eastern Standard Time
Eastern Standard Time
Friday, September 26, 2008 08:30 PM Central Daylight Time
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class TimeZoneExtracter {

    public static final void main(String[] args) throws ParseException {
        DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
        System.out.println(dbFormatter.getTimeZone());
        dbFormatter.parse("Fr, September 26, 2008 8:30 PM Eastern Daylight Time");
        System.out.println(dbFormatter.getTimeZone());
    }

}
输出:

sun.util.calendar.ZoneInfo[id=“欧洲/柏林”。。。 sun.util.calendar.ZoneInfo[id=“非洲/亚的斯亚贝巴”

这就是你想要的结果吗?

@Ed Thomas:

我尝试了一些与您的示例非常相似的方法,但得到了非常不同的结果:

String testString = "Friday, September 26, 2008 8:30 PM Pacific Standard Time";
DateFormat df = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");

System.out.println("The default TimeZone is: " + TimeZone.getDefault().getDisplayName());

System.out.println("DateFormat timezone before parse: " + df.getTimeZone().getDisplayName());

Date date = df.parse(testString);

System.out.println("Parsed [" + testString + "] to Date: " + date);

System.out.println("DateFormat timezone after parse: " + df.getTimeZone().getDisplayName());
输出:

默认时区为:东部标准时间

解析前的DateFormat时区:东部标准时间

解析[2008年9月26日星期五太平洋标准时间晚上8:30]到日期:美国东部夏令时2008年9月27日星期六00:30:00

解析后的DateFormat时区:东部标准时间

看起来像是
DateFormat.getTimeZone()
parse()
前后返回相同的时区…即使在调用
parse()
之前我抛出了一个显式的
setTimeZone()


查看DateFormat和SimpleDateFormat的源代码,看起来像是
getTimeZone()
只返回基础日历的时区…除非您指定要使用的特定区域设置/时区,否则它将默认为默认区域设置/时区的日历。

Ed正确无误。您希望在解析时间后在DateFormat对象上显示时区

 String rawDate = "Friday, September 26, 2008 8:30 PM Eastern Daylight Time";
 DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
 Date scheduledDate = dbFormatter.parse(rawDate);

 System.out.println(rawDate); 
 System.out.println(scheduledDate); 
 System.out.println(dbFormatter.getTimeZone().getDisplayName());
产生

Friday, September 26, 2008 8:30 PM Eastern Daylight Time
Fri Sep 26 20:30:00 CDT 2008
Eastern Standard Time

我建议您查看Joda Time date and Time API。我最近已经成为它的信徒,因为它往往比Java中内置的日期和时间支持要好得多。特别是,您应该查看DateTimeZone类。希望这对您有所帮助

tl;dr java.time 现代的方法是使用java.time类。问题和其他答案使用麻烦的旧遗留日期时间类或Joda时间项目,这两个类现在都被java.time类取代

使用格式化模式定义一个
DateTimeFormatter
对象以匹配您的数据

DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEEE, MMMM d, uuuu h:m a zzzz" );
指定一个
区域设置
,以指定日期名称和月份名称的人类语言,以及其他格式问题的文化规范

f = f.withLocale( Locale.US );
最后,进行解析以获取
zoneDateTime
对象

String input = "Friday, September 26, 2008 8:30 PM Eastern Daylight Time" ;
ZonedDateTime zdt = ZonedDateTime.parse( input , f );
zdt.toString():2008-09-26T20:30-04:00[美国/纽约]

您可以从
ZoneDateTime
中请求时区,表示为
ZoneId
对象。如果需要有关时区的更多信息,您可以询问
ZoneId

ZoneId z = zdt.getZone();

ISO 8601 避免以这种糟糕的格式交换日期-时间数据。不要使用英语,不要使用诸如日期名称之类的内容来辅助输出,也不要使用伪时区,例如
东部夏时制

对于时区:以
大陆/地区
的格式指定一个,例如,或
太平洋/奥克兰
。切勿使用3-4个字母的缩写,例如
EST
IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)

要将日期时间值序列化为文本,请仅使用格式。java.time类在解析/生成字符串以表示其值时默认使用这些格式


关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,如,&

该项目现已启动,建议迁移到java.time

要了解更多信息,请参阅.和搜索堆栈溢出以获取许多示例和解释。规范为

从哪里获得java.time类

  • 后来
    • 内置的
    • 标准JavaAPI的一部分,带有捆绑实现
    • Java9添加了一些次要功能和修复
  • 一个