I am pretty new to Java and I am a little stuck with using SimpleDateFormat
and Calendar
. I have a Date-Object and want to extract a GMT datestring like yyyy-MM-dd HH:mm:ss
. I live in Germany and at the mom开发者_如何转开发ent we are GMT +0200. My Date-Object's time is for example 2011-07-18 13:00:00
. What I need now is 2011-07-18 11:00:00
. The offset for my timezone should be calculated automatically.
I tried something like this, but I guess there is a fault somewhere:
private String toGmtString(Date date){
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
TimeZone timeZone = TimeZone.getDefault();
Calendar cal = Calendar.getInstance(new SimpleTimeZone(timeZone.getOffset(date.getTime()), "GMT"));
sd.setCalendar(cal);
return sd.format(date);
}
On some devices the datestring is returned like I want it to. On other devices the offset isn't calculated right and I receive the date and time from the input date-object. Can you give me some tips or advices? I guess my way off getting the default timezone does not work?
private String toGmtString(Date date){
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sd.setTimeZone(TimeZone.getTimeZone("GMT"));
return sd.format(date);
}
You don't need to create a new SimpleTimeZone
, because you aren't inventing a new timezone - there are 2 existing timezones that come into play in your program, GMT and your default one.
You also don't need to modify your existing date object, because you don't want to represent a different point in time - you only want a different way to display the same point in time.
All you need to do is tell the SimpleDateFormat
which timezone to use in formatting.
private String toGmtString(Date date){
//date formatter
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//getting default timeZone
TimeZone timeZone = TimeZone.getDefault();
//getting current time
Calendar cal = Calendar.getInstance()
cal.setTime(date) ;
//adding / substracting curren't timezone's offset
cal.add(Calendar.MILLISECOND, -1 * timeZone.getRawOffset());
//formatting and returning string of date
return sd.format(cal.getTime());
}
java.time
Using java.time
, the modern date-time API, there are many ways to do it:
- Parse to
LocalDateTime
➡️ Combine it with your timezone to getZonedDateTime
➡️ Convert toInstant
➡️ Convert toZonedDateTime
usingInstant#atZone
and UTC timezone.
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "2011-07-18 13:00:00";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
// Using ZoneId.of("Europe/Berlin") for the demo. Change it to
// ZoneId.systemDefault()
Instant instant = ldt.atZone(ZoneId.of("Europe/Berlin")).toInstant();
ZonedDateTime zdtUtc = instant.atZone(ZoneId.of("Etc/UTC"));
System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
}
}
- Parse to
LocalDateTime
➡️ Combine it with your timezone to getZonedDateTime
➡️ Convert toInstant
➡️ Convert toZonedDateTime
usingZonedDateTime#ofInstant
and UTC timezone.
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "2011-07-18 13:00:00";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
// Using ZoneId.of("Europe/Berlin") for the demo. Change it to
// ZoneId.systemDefault()
Instant instant = ldt.atZone(ZoneId.of("Europe/Berlin")).toInstant();
ZonedDateTime zdtUtc = ZonedDateTime.ofInstant(instant, ZoneId.of("Etc/UTC"));
System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
}
}
- Using
ZonedDateTime#withZoneSameInstant
:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "2011-07-18 13:00:00";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
// Using ZoneId.of("Europe/Berlin") for the demo. Change it to
// ZoneId.systemDefault()
ZonedDateTime zdtPak = ldt.atZone(ZoneId.of("Europe/Berlin"));
ZonedDateTime zdtUtc = zdtPak.withZoneSameInstant(ZoneId.of("Etc/UTC"));
System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
}
}
- Using
DateTimeFormatter#withZone
andZonedDateTime#withZoneSameInstant
:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "2011-07-18 13:00:00";
// Using ZoneId.of("Europe/Berlin") for the demo. Change it to
// ZoneId.systemDefault()
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH)
.withZone(ZoneId.of("Europe/Berlin"));
ZonedDateTime zdtPak = ZonedDateTime.parse(strDateTime, dtfInput);
ZonedDateTime zdtUtc = zdtPak.withZoneSameInstant(ZoneId.of("Etc/UTC"));
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
System.out.println(zdtUtc.format(dtfOutput)); // 2011-07-18 11:00:00
}
}
Learn more about the modern date-time API* from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
精彩评论