如何设置java.util.Date的偏移量?
How to set offset of a java.util.Date?
我有一个字符串形式的日期 - 15Sep20162040
,我必须将其格式化为另一种格式,时区为 2016-09-15T20:40:00+0400
。
我做了如下操作:
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class DateFormatExample {
private static SimpleDateFormat offsetDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZ");
private static SimpleDateFormat dateFormatter = new SimpleDateFormat(
"ddMMMyyyyHHmm");
public static void main(String[] args) throws ParseException {
String date = "15Sep20162040";
String result = offsetDateFormat.format(dateFormatter.parse(date));
System.out.println(result); // 2016-09-15T20:40:00+0400
}
}
现在,我必须根据时区差异修改输出,例如,如果差异为 +0100
,输出应类似于:2016-09-15T20:40:00+0100
,如果差异为 -0200
,则输出应该类似于:2016-09-15T20:40:00-0200
.
如何实现?
您可以使用SimpleDateFormat
的setTimeZone
方法如下:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class DateFormatExample {
private static SimpleDateFormat offsetDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZ");
private static SimpleDateFormat dateFormatter = new SimpleDateFormat(
"ddMMMyyyyHHmm");
public static void main(String[] args) throws ParseException {
String date = "15Sep20162040";
String result = offsetDateFormat.format(dateFormatter.parse(date));
System.out.println(result); // 2016-09-15T20:40:00+0400
offsetDateFormat.setTimeZone(TimeZone.getTimeZone("GMT-8:00"));
result = offsetDateFormat.format(dateFormatter.parse(date));
System.out.println(result);
}
}
如果您只想更改 result
末尾的时区,请尝试以下操作:
String offset = "GMT-8:00";
String date = "15Sep20162040";
date = date+" "+offset;
SimpleDateFormat dateFormatter2 = new SimpleDateFormat("ddMMMyyyyHHmm Z");
SimpleDateFormat offsetDateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
offsetDateFormat2.setTimeZone(TimeZone.getTimeZone(offset));
String result = offsetDateFormat2.format(dateFormatter2.parse(date));
System.out.println(result);
希望对您有所帮助。
tl;博士
ZonedDateTime zdt =
LocalDateTime.parse ( "15Sep20162040" ,
DateTimeFormatter.ofPattern ( "ddMMMyyyyHHmm" )
.withLocale( Locale.English )
)
.atZone ( ZoneId.of ( "America/Puerto_Rico" ) );
2016-09-15T20:40-04:00[America/Puerto_Rico]
zdt.atZone( ZoneId.of ( "Pacific/Auckland" ) ) // Same moment viewed through different wall-clock time
2016-09-16T12:40+12:00[Pacific/Auckland]
使用java.time
避免麻烦的旧日期时间 类,现在被 java.time 类.
取代
定义格式模式以匹配您的输入字符串。
String input = "15Sep20162040";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "ddMMMyyyyHHmm" ).withLocale ( Locale.ENGLISH );
顺便说一句,这是一种糟糕的日期时间字符串格式。它采用英语,滥用英语,使用不正确的月份名称缩写,并且令人困惑和模棱两可。相反,在将日期时间值序列化为文本时使用标准 ISO 8601 格式。
未分区
将输入字符串解析为 LocalDateTime
since it lacks any info about offset-from-UTC 或时区。
LocalDateTime ldt = LocalDateTime.parse ( input , f );
了解没有偏移量或时区,这个 LocalDateTime
对象没有实际意义。它代表许多可能的时刻,但不是时间轴上的特定点。例如,新西兰奥克兰的中午与印度加尔各答的中午不同,后者比法国巴黎的中午早。
分配与 UTC 的偏移量
您表示此日期时间是 offset-from-UTC 比 UTC (-04:00) 晚四个小时的时刻。所以接下来我们应用一个 ZoneOffset
来获得一个 OffsetDateTime
对象。
提示:始终在您的 UTC 偏移量字符串中包含冒号、分钟和填充零。虽然 ISO 8601 标准没有要求,但通用软件库和协议需要更完整的格式。
ZoneOffset offset = ZoneOffset.ofHours( -4 );
OffsetDateTime odt = ldt.atOffset( offset );
指定时区
如果根据上下文您知道时区而不仅仅是偏移量,请使用 ZoneId
to instantiate a ZonedDateTime
object. A time zone is an offset plus a set of rules for handling anomalies such as Daylight Saving Time (DST)。
以continent/region
的格式指定一个proper time zone name。切勿使用 3-4 个字母的缩写,例如 EST
或 IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Puerto_Rico" );
ZonedDateTime zdt = ldt.atZone( z );
不同时区
你的问题快结束时还不清楚,关于更改偏移量。如果您的目标是通过不同时区的不同镜头查看日期时间,您可以通过创建新的 ZonedDateTime
对象轻松进行调整。为每个分配不同的时区。
请注意,所有这些日期时间对象(zdt、zKolkata 和 zAuckland)代表同一时刻,时间轴上的同一点。每个都呈现不同的 wall-clock time 但 相同的同时时刻 .
ZoneId zKolkata = ZoneId.of ( "Asia/Kolkata" );
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant ( zKolkata );
ZoneId zAuckland = ZoneId.of ( "Pacific/Auckland" );
ZonedDateTime zdtAuckland = zdt.withZoneSameInstant ( zAuckland );
System.out.println ( "input: " + input + " | ldt: " + ldt + " | odt: " + odt + " | zdt: " + zdt + " | zdtKolkata " + zdtKolkata + " | zdtAuckland: " + zdtAuckland );
转储到控制台。
input: 15Sep20162040 | ldt: 2016-09-15T20:40 | odt: 2016-09-15T20:40-04:00 | zdt: 2016-09-15T20:40-04:00[America/Puerto_Rico] | zdtKolkata 2016-09-16T06:10+05:30[Asia/Kolkata] | zdtAuckland: 2016-09-16T12:40+12:00[Pacific/Auckland]
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些 类 取代了麻烦的旧日期时间 类,例如 java.util.Date
、.Calendar
和 java.text.SimpleDateFormat
。
Joda-Time project, now in maintenance mode,建议迁移到java.time。
要了解更多信息,请参阅 Oracle Tutorial。并在 Stack Overflow 中搜索许多示例和解释。
许多 java.time 功能被反向移植到 ThreeTen-Backport and further adapted to Android in ThreeTenABP (see 中的 Java 6 & 7)。
ThreeTen-Extra 项目扩展了 java.time 并增加了 类。该项目是未来可能添加到 java.time 的试验场。您可能会在这里找到一些有用的 类,例如 Interval
、YearWeek
、YearQuarter
等。
我有一个字符串形式的日期 - 15Sep20162040
,我必须将其格式化为另一种格式,时区为 2016-09-15T20:40:00+0400
。
我做了如下操作:
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class DateFormatExample {
private static SimpleDateFormat offsetDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZ");
private static SimpleDateFormat dateFormatter = new SimpleDateFormat(
"ddMMMyyyyHHmm");
public static void main(String[] args) throws ParseException {
String date = "15Sep20162040";
String result = offsetDateFormat.format(dateFormatter.parse(date));
System.out.println(result); // 2016-09-15T20:40:00+0400
}
}
现在,我必须根据时区差异修改输出,例如,如果差异为 +0100
,输出应类似于:2016-09-15T20:40:00+0100
,如果差异为 -0200
,则输出应该类似于:2016-09-15T20:40:00-0200
.
如何实现?
您可以使用SimpleDateFormat
的setTimeZone
方法如下:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class DateFormatExample {
private static SimpleDateFormat offsetDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssZ");
private static SimpleDateFormat dateFormatter = new SimpleDateFormat(
"ddMMMyyyyHHmm");
public static void main(String[] args) throws ParseException {
String date = "15Sep20162040";
String result = offsetDateFormat.format(dateFormatter.parse(date));
System.out.println(result); // 2016-09-15T20:40:00+0400
offsetDateFormat.setTimeZone(TimeZone.getTimeZone("GMT-8:00"));
result = offsetDateFormat.format(dateFormatter.parse(date));
System.out.println(result);
}
}
如果您只想更改 result
末尾的时区,请尝试以下操作:
String offset = "GMT-8:00";
String date = "15Sep20162040";
date = date+" "+offset;
SimpleDateFormat dateFormatter2 = new SimpleDateFormat("ddMMMyyyyHHmm Z");
SimpleDateFormat offsetDateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
offsetDateFormat2.setTimeZone(TimeZone.getTimeZone(offset));
String result = offsetDateFormat2.format(dateFormatter2.parse(date));
System.out.println(result);
希望对您有所帮助。
tl;博士
ZonedDateTime zdt =
LocalDateTime.parse ( "15Sep20162040" ,
DateTimeFormatter.ofPattern ( "ddMMMyyyyHHmm" )
.withLocale( Locale.English )
)
.atZone ( ZoneId.of ( "America/Puerto_Rico" ) );
2016-09-15T20:40-04:00[America/Puerto_Rico]
zdt.atZone( ZoneId.of ( "Pacific/Auckland" ) ) // Same moment viewed through different wall-clock time
2016-09-16T12:40+12:00[Pacific/Auckland]
使用java.time
避免麻烦的旧日期时间 类,现在被 java.time 类.
取代定义格式模式以匹配您的输入字符串。
String input = "15Sep20162040";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "ddMMMyyyyHHmm" ).withLocale ( Locale.ENGLISH );
顺便说一句,这是一种糟糕的日期时间字符串格式。它采用英语,滥用英语,使用不正确的月份名称缩写,并且令人困惑和模棱两可。相反,在将日期时间值序列化为文本时使用标准 ISO 8601 格式。
未分区
将输入字符串解析为 LocalDateTime
since it lacks any info about offset-from-UTC 或时区。
LocalDateTime ldt = LocalDateTime.parse ( input , f );
了解没有偏移量或时区,这个 LocalDateTime
对象没有实际意义。它代表许多可能的时刻,但不是时间轴上的特定点。例如,新西兰奥克兰的中午与印度加尔各答的中午不同,后者比法国巴黎的中午早。
分配与 UTC 的偏移量
您表示此日期时间是 offset-from-UTC 比 UTC (-04:00) 晚四个小时的时刻。所以接下来我们应用一个 ZoneOffset
来获得一个 OffsetDateTime
对象。
提示:始终在您的 UTC 偏移量字符串中包含冒号、分钟和填充零。虽然 ISO 8601 标准没有要求,但通用软件库和协议需要更完整的格式。
ZoneOffset offset = ZoneOffset.ofHours( -4 );
OffsetDateTime odt = ldt.atOffset( offset );
指定时区
如果根据上下文您知道时区而不仅仅是偏移量,请使用 ZoneId
to instantiate a ZonedDateTime
object. A time zone is an offset plus a set of rules for handling anomalies such as Daylight Saving Time (DST)。
以continent/region
的格式指定一个proper time zone name。切勿使用 3-4 个字母的缩写,例如 EST
或 IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Puerto_Rico" );
ZonedDateTime zdt = ldt.atZone( z );
不同时区
你的问题快结束时还不清楚,关于更改偏移量。如果您的目标是通过不同时区的不同镜头查看日期时间,您可以通过创建新的 ZonedDateTime
对象轻松进行调整。为每个分配不同的时区。
请注意,所有这些日期时间对象(zdt、zKolkata 和 zAuckland)代表同一时刻,时间轴上的同一点。每个都呈现不同的 wall-clock time 但 相同的同时时刻 .
ZoneId zKolkata = ZoneId.of ( "Asia/Kolkata" );
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant ( zKolkata );
ZoneId zAuckland = ZoneId.of ( "Pacific/Auckland" );
ZonedDateTime zdtAuckland = zdt.withZoneSameInstant ( zAuckland );
System.out.println ( "input: " + input + " | ldt: " + ldt + " | odt: " + odt + " | zdt: " + zdt + " | zdtKolkata " + zdtKolkata + " | zdtAuckland: " + zdtAuckland );
转储到控制台。
input: 15Sep20162040 | ldt: 2016-09-15T20:40 | odt: 2016-09-15T20:40-04:00 | zdt: 2016-09-15T20:40-04:00[America/Puerto_Rico] | zdtKolkata 2016-09-16T06:10+05:30[Asia/Kolkata] | zdtAuckland: 2016-09-16T12:40+12:00[Pacific/Auckland]
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些 类 取代了麻烦的旧日期时间 类,例如 java.util.Date
、.Calendar
和 java.text.SimpleDateFormat
。
Joda-Time project, now in maintenance mode,建议迁移到java.time。
要了解更多信息,请参阅 Oracle Tutorial。并在 Stack Overflow 中搜索许多示例和解释。
许多 java.time 功能被反向移植到 ThreeTen-Backport and further adapted to Android in ThreeTenABP (see
ThreeTen-Extra 项目扩展了 java.time 并增加了 类。该项目是未来可能添加到 java.time 的试验场。您可能会在这里找到一些有用的 类,例如 Interval
、YearWeek
、YearQuarter
等。