我需要使用几种日期格式来解析一个日期,假设一个特定的时区,然后将它输出到另一个时区(即UTC)。我本来希望DateTimeFormatterBuilder能帮上忙,但似乎解析器和打印机上附加的时区信息丢失了/被忽略了吗?
见测试和输出:
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.joda.time.format.DateTimeParser;
import org.junit.Test;
public class JodaBuilderTest {
@Test
public void aTestOfTimeZoneRetentionOfFormattersPassedToBuilder() throws Exception {
String [] parsePatterns = new String [] { "MM/dd/yyyy HH:mm:ss", "MM/dd/yyyy" };
String printPattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ";
String inputString = "08/03/2015 01:01:01";
DateTimeZone tz = DateTimeZone.forOffsetHours(-3);
DateTimeParser[] parsers = new DateTimeParser[parsePatterns.length];
for (int index = 0; index < parsePatterns.length; index++) {
parsers[index] = DateTimeFormat.forPattern(parsePatterns[index]).withZone(tz).getParser();
}
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder()
.append(DateTimeFormat.forPattern(printPattern).withZoneUTC().getPrinter(), parsers);
DateTimeFormatter parser = builder.toFormatter();
DateTimeZone parserdtz = parser.getZone();
System.out.println("parserdtz: " + parserdtz);
DateTime dt = parser.parseDateTime(inputString);
System.out.println("parser zone is " + dt.getZone());
String dtout = dt.toString();
System.out.println("expecting UTC-3: 2015-08-03T01:01:01.000-03:00");
System.out.println("got:\t\t" + dtout);
String dtoutFmt = dt.toString(parser);
System.out.println("expecting UTC: 2015-08-03T04:01:01.000-00:00");
System.out.println("got:\t\t" + dtoutFmt);
org.junit.Assert.assertEquals("2015-08-03T04:01:01.000-00:00", dtoutFmt);
}
}输出如下
parserdtz: null
parser zone is America/New_York
expecting UTC-3: 2015-08-03T01:01:01.000-03:00
got: 2015-08-03T01:01:01.000-04:00
expecting UTC: 2015-08-03T04:01:01.000-00:00
got: 2015-08-03T01:01:01.000-04:00因此,它似乎忽略了解析器上的UTC-3集和打印机上的UTC集,并默认为系统区域(EDT)。我是错过了什么,还是这是我所期待的行为?我唯一的办法就是不使用建筑商吗?我也不能在parser上设置区域,即DateTimeFormatter parser = builder.toFormatter().withZone(DateTimeZone.forOffsetHours(-3));,因为这将覆盖打印机。我想我可以为打印机创建一个单独的格式化程序,但是打印机参数对生成器的作用是什么呢?我应该把它设置为空吗?感觉不太对劲。
发布于 2016-01-22 14:23:06
以下是一些澄清:
DateTimeParser和DateTimePrinter实例根据特定的格式模式解析/打印DateTime。但是,时区和区域设置不是打印机/解析器实例的一部分。它们是在运行时提供的,以个案为基础。见DateTimePrinter.printTo的签名
void printTo(StringBuffer buf,
long instant,
Chronology chrono,
int displayOffset,
DateTimeZone displayZone, // zone provided at runtime
Locale locale)至于打印机-它可以读取任何时区,所以用一个不相关的配置它。
请记住来自DateTimePrinter/Parser javadocs的片段:
用于创建/解析日期时间文本表示的内部接口。
因此,打印机/解析器本身没有内部设置的时区。您可以删除打印机/解析器上的withZone(tz)/withZoneUTC()配置,因为它们无论如何都不会更改任何内容。
然而,DateTimeFormatter已经做到了。当涉及时区时,这是您应该使用的顶级API。如果在格式化程序上设置时区X,它将能够读取任何时区字符串,但是创建的DateTime实例将被转换为时区X。同样,当打印任何DateTime实例(在任何时区中)时,它将被打印为转换为时区X。如果确实试图将字符串解析为-03:00时区,则需要一个DateTimeFormatter实例,当您想要在UTC中打印它时,需要一个不同的格式化程序实例。
因此,拥有原始的formatter (从parser重命名),您可以这样做
DateTime dt = formatter.withZone(DateTimeZone.forID("-03:00")).parseDateTime(inputString);和印刷方面:
String dtoutFmt = dt.toString(formatter.withZoneUTC());我确信,如果您对变量使用了相关的名称--使用formatter作为DateTimeFormatter实例,以避免与实际DateTimeParser的混淆,这会更加清楚一些。
https://stackoverflow.com/questions/34820021
复制相似问题