通过 DateTimeFormatter 将时区传递给 DateTimeFormatterBuilder 时,时区是否丢失?
Are time zones lost when passing them via DateTimeFormatter to DateTimeFormatterBuilder?
我需要使用假设特定时区的几种日期格式来解析日期,然后将其输出到另一个时区(即 UTC)。我希望 DateTimeFormatterBuilder 可以提供帮助,但似乎附加到解析器和打印机的时区信息是 lost/ignored?
查看测试和输出:
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));
因为那会覆盖打印机。我想我可以为打印机创建一个单独的格式化程序,但是构建器的打印机参数的目的是什么?我应该将其设置为空吗?感觉不对。
这里有一些说明:
DateTimeParser
and DateTimePrinter
instances parse/print the DateTime
according to a certain formatting pattern. However, the time zone and the locale are not a part of the printer/parser instance. They are provided during runtime, on a case-by-case basis. See the signature of DateTimePrinter.printTo
:
void printTo(StringBuffer buf,
long instant,
Chronology chrono,
int displayOffset,
DateTimeZone displayZone, // zone provided at runtime
Locale locale)
至于打印机-它可以读取任何时区,所以配置一个没有关系。
记住 DateTimePrinter/Parser
javadocs 中的片段:
Internal interface for creating/parsing textual representations of datetimes.
因此,printer/parser 本身并没有在内部设置时区。您可以删除 printers/parsers 上的 withZone(tz)
/withZoneUTC()
配置,因为它们无论如何都不会改变任何东西。
不过,DateTimeFormatter
有了。这是 top-level 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
混淆]s.
我需要使用假设特定时区的几种日期格式来解析日期,然后将其输出到另一个时区(即 UTC)。我希望 DateTimeFormatterBuilder 可以提供帮助,但似乎附加到解析器和打印机的时区信息是 lost/ignored?
查看测试和输出:
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));
因为那会覆盖打印机。我想我可以为打印机创建一个单独的格式化程序,但是构建器的打印机参数的目的是什么?我应该将其设置为空吗?感觉不对。
这里有一些说明:
DateTimeParser
and DateTimePrinter
instances parse/print the DateTime
according to a certain formatting pattern. However, the time zone and the locale are not a part of the printer/parser instance. They are provided during runtime, on a case-by-case basis. See the signature of DateTimePrinter.printTo
:
void printTo(StringBuffer buf,
long instant,
Chronology chrono,
int displayOffset,
DateTimeZone displayZone, // zone provided at runtime
Locale locale)
至于打印机-它可以读取任何时区,所以配置一个没有关系。
记住 DateTimePrinter/Parser
javadocs 中的片段:
Internal interface for creating/parsing textual representations of datetimes.
因此,printer/parser 本身并没有在内部设置时区。您可以删除 printers/parsers 上的 withZone(tz)
/withZoneUTC()
配置,因为它们无论如何都不会改变任何东西。
不过,DateTimeFormatter
有了。这是 top-level 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
混淆]s.