从字符串中提取TimeZone对象的最佳方法?

时间:2020-03-05 18:59:30  来源:igfitidea点击:

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

Friday, September 26, 2008 8:30 PM Eastern Daylight Time

我可以使用SimpleDateFormat轻松将其解析为Date

DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
Date scheduledDate = dbFormatter.parse(rawDate);

我想做的是从此字符串中提取一个TimeZone对象。运行该应用程序的JVM中的默认TimeZone是GMT,所以我不能使用上面解析的" Date"中的.getTimezoneOffset()(因为它将返回默认的TimeZone)。

除了标记原始字符串并找到时区字符串的开始位置(因为我知道格式将始终为EEEE,MMMM dd,yyyy hh:mm aa zzzz)之外,还有一种使用DateFormat / SimpleDateFormat / Date / Calendar的方法提取一个TimeZone对象的API,该对象将具有与我用`DateFormat.parse()解析过的字符串相同的TimeZone?

关于Java API中的"日期"与"日历"的一个令我感到困惑的事情是,"日历"应该在所有地方替换"日期" ...但是他们决定,哦,还是让我们仍然使用"日期"在" DateFormat"类中。

解决方案

回答

作为部分解决方案,我们可以使用RegEx匹配来获取时区,因为我们之前总是会有相同的文本。上午或者下午。

我对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

我实际上发现这有些令人惊讶。但是,我想这表明问题的答案是在解析后仅在格式化程序上调用getTimeZone。

编辑:
以上是与Sun的JDK 1.6一起运行的。

回答

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

玩一下示例,我得到以下信息:

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="Europe/Berlin"...
  sun.util.calendar.ZoneInfo[id="Africa/Addis_Ababa"...

这是我们想要的结果吗?

回答

@埃德·托马斯(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());

输出:

The default TimeZone is: Eastern Standard Time
  
  DateFormat timezone before parse: Eastern Standard Time
  
  Parsed [Friday, September 26, 2008 8:30 PM Pacific Standard Time] to Date: Sat Sep 27 00:30:00 EDT 2008
  
  DateFormat timezone after parse: Eastern Standard Time

好像DateFormat.getTimeZone()parse()...之前和之后返回相同的TimeZone ...即使我在调用parse()之前抛出显式的setTimeZone()`。

在查看DateFormat和SimpleDateFormat的源代码时,getTimeZone()似乎只返回底层Calendar的TimeZone ...,除非我们指定要使用的特定日历,否则它将默认为默认Locale / TimeZone的Calendar。

回答

埃德说得对。我们需要在解析时间之后在DateFormat对象上使用timeZone。

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日期和时间API。我最近已转变为对此的信奉者,因为它往往比Java中对日期和时间的内置支持要优越得多。特别是,我们应该检出DateTimeZone类。希望这可以帮助。

http://joda-time.sourceforge.net/

http://joda-time.sourceforge.net/api-release/index.html