我需要使用几种日期格式解析日期,假设某个时区,然后在另一个时区(即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));
因为这会覆盖打印机。我想我可以为打印机创建一个单独的格式化程序,但那么构建器的打印机参数的目的是什么?我应该将其设置为null吗?感觉不对。
答案 0 :(得分:0)
以下是一些澄清:
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
混淆