问题
I have a Date as a String - 15Sep20162040
, which I have to format it into another format with Timezone as 2016-09-15T20:40:00+0400
.
What I did to do it as follows:
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
}
}
Now, I have to modify the output based on timezone difference, for example if difference is +0100
, output should resemble as: 2016-09-15T20:40:00+0100
and if difference is -0200
, output should resemble as: 2016-09-15T20:40:00-0200
.
How can I achieve it?
回答1:
You can use SimpleDateFormat
's setTimeZone
method as below:
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);
}
}
If you simply want to change the timezone at the end of result
, please try the following:
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);
Hope this helps.
回答2:
tl;dr
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]
Using java.time
Avoid the troublesome old date-time classes, now supplanted by the java.time classes.
Define a formatting pattern to match your input string.
String input = "15Sep20162040";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "ddMMMyyyyHHmm" ).withLocale ( Locale.ENGLISH );
By the way, this is a terrible format for a date-time string. It assumes English, abuses English with incorrect abbreviation of month name, and is confusing and ambiguous. Instead, use the standard ISO 8601 formats when serializing date-time values to text.
Un-zoned
Parse the input string as a LocalDateTime since it lacks any info about offset-from-UTC or time zone.
LocalDateTime ldt = LocalDateTime.parse ( input , f );
Understand that without an offset or time zone, this LocalDateTime
object has no real meaning. It represents many possible moments, but not a specific point on the timeline. For example, noon in Auckland NZ is a different moment than noon in Kolkata India which is an earlier moment than noon in Paris France.
Assign an offset-from-UTC
You indicate this date-time was intended to be a moment with an offset-from-UTC of four hours behind UTC (-04:00). So next we apply a ZoneOffset
to get a OffsetDateTime
object.
Tip: Always include the colon and the minutes and padding zeros in your offset-from-UTC strings. While not required by the ISO 8601 standard, common software libraries and protocols expect the fuller formatting.
ZoneOffset offset = ZoneOffset.ofHours( -4 );
OffsetDateTime odt = ldt.atOffset( offset );
Assign a time zone
If by your context you knew of a time zone rather than a mere offset, use a 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).
Specify a proper time zone name in the format of continent/region
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Puerto_Rico" );
ZonedDateTime zdt = ldt.atZone( z );
Different time zones
Your question is not clear near the end, about changing offsets. If your goal is to view the date-time through the various lenses of various time zones, you can easily adjust by creating new ZonedDateTime
objects. Assign a different time zone to each.
Note that all these date-time objects (zdt, zKolkata, and zAuckland) represent the same moment, the same point on the timeline. Each presents a different wall-clock time but for the same simultaneous moment.
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 );
Dump to console.
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]
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
来源:https://stackoverflow.com/questions/39557374/how-to-set-offset-of-a-java-util-date