从字符串中提取TimeZone对象的最佳方法?
我有一个数据库字段,其中包含原始日期字段(存储为字符数据),例如
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