Java 从字符串中提取时区对象的最佳方法?
我有一个数据库字段,其中包含一个原始日期字段(存储为字符数据),例如 2008年9月26日星期五东部夏令时晚上8:30 我可以使用SimpleDataFormat轻松地将其解析为日期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); 我想做的是从这个字符串中提取一个时区对象。此应用
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
vsCalendar
让我感到困扰的一点是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添加了一些次要功能和修复
- 一个