I am having trouble figuring out why the timezone for the code below keeps showing UTC instead of EST. On my local computer it show EST, even if I am in MST time but on the actual server it keeps showing UTC. Any clue?
Mon Nov 9 2015 1:58:49 PM UTC
#JsonIgnore
public String getDateCreatedFormatted() {
Calendar calendar = Calendar.getInstance();
calendar.setTime(getDateCreated());
calendar.setTimeZone(TimeZone.getTimeZone("EST"));
SimpleDateFormat format = new SimpleDateFormat("EEE MMM d yyyy h:mm:ss a z");
return format.format(calendar.getTime());
}
You've set the calendar to EST, but you haven't set the time zone on the SimpleDateFormat, which is the one use for formatting. Just use:
format.setTimeZone(TimeZone.getTimeZone("America/New_York"));
before you format the Date. You also don't need the Calendar at all, by the looks of it:
#JsonIgnore
public String getDateCreatedFormatted() {
SimpleDateFormat format = new SimpleDateFormat("EEE MMM d yyyy h:mm:ss a z", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("America/New_York"));
return format.format(getDateCreated());
}
Also I would strongly advise you to use full time zone IDs as above, rather than the abbreviations like "EST" which are ambiguous. (There are two problems there - firstly, EST can mean different things in different locations; secondly, the US EST should always mean Eastern standard time, whereas I assume you want to format using Eastern time, either standard or daylight depending on whether daylight saving time is in effect or not.)
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time, the modern Date-Time API:
#JsonIgnore
public String getDateCreatedFormatted() {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/New_York"));
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM d uuuu h:mm:ss a z", Locale.ENGLISH);
return dtf.format(now);
}
ONLINE DEMO
Note: Never use SimpleDateFormat or DateTimeFormatter without a Locale.
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.
Related
I need to generate a new Date(); already with the correct time zone, because I need to record the date and time that a new data is received on my server. (I know that you can use the SimpleDateFormat, but it requires to parse a already created string).
I'm using Java + Spring Boot.
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time, the modern Date-Time API: You can use ZonedDateTime with the applicable ZoneId.
Demo:
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
// Use the applicable ZoneId
ZoneId zoneId = ZoneId.of("Asia/Dubai");
ZonedDateTime now = ZonedDateTime.now(zoneId);
System.out.println(now);
}
}
Output from a sample run:
2021-10-30T02:26:07.471319+04:00[Asia/Dubai]
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time. Check this answer and this answer to learn how to use java.time API with JDBC.
A note on java.util.Date:
A java.util.Date object simply represents an instant on the timeline — a wrapper around the number of milliseconds since the UNIX epoch (January 1, 1970, 00:00:00 GMT). Since it does not hold any timezone information, its toString function applies the JVM's timezone to return a String in the format, EEE MMM dd HH:mm:ss zzz yyyy, derived from this milliseconds value. To get the String representation of the java.util.Date object in a different format and timezone, you need to use SimpleDateFormat with the desired format and the applicable timezone e.g.
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String strDateNewYork = sdf.format(date);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = sdf.format(date);
* 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. Note that Android 8.0 Oreo already provides support for java.time.
Use DateFormat. For example,
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = isoFormat.parse("2010-05-23T09:01:02");
I have to call a web service which is expecting a Date field but they want it in the following format YYYY-MM-DDThh:mm:ss.sssZ. How can I do this?
I tried the following
OffsetDateTime transactionTime = OffsetDateTime.now(ZoneOffset.UTC);
Date.from(transactionTime.toInstant());
but this didn't work. transactionTime is 2021-06-01T15:11:09.942843400Z, but Date.from converts it to Tue Jun 01 11:11:09 EDT 2021.
BTW, I'm using Java 11
Instant.now().toString()
See that code run live at IdeOne.com.
2021-06-01T15:21:16.783779Z
That format is defined in the ISO 8601 standard. The Z on end means an offset-from-UTC of zero hours-minutes-seconds. Pronounced “Zulu”.
Use java.time.Instant to represent a moment as seen in UTC.
Going the other direction, from text to object.
Instant.parse( "2021-06-01T15:21:16.783779Z" )
If you want only milliseconds, you can lop off any microseconds and nanoseconds by truncating.
Instant.now().truncatedTo( ChronoUnit.MILLIS ) ;
Never use the legacy Date class. Use only the java.time classes.
Use DateTimeFormatter to format the Date-Time object
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
OffsetDateTime transactionTime = OffsetDateTime.now(ZoneOffset.UTC);
String formatted = transactionTime.format(dtf);
System.out.println(formatted);
}
}
Output:
2021-06-01T15:49:45.198Z
Learn more about the modern Date-Time API from Trail: Date Time.
What if I want to use java.util.Date?
For any reason, if you need to convert this object of OffsetDateTime to an object of java.util.Date, you can do so as follows:
Date date = Date.from(transactionTime.toInstant());
Note that a java.util.Date object is not a real Date-Time object like the modern Date-Time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since Date does not have timezone information, it applies the JVM's timezone to return the value of Date#toString in the format, EEE MMM dd HH:mm:ss z yyyy calculated from this milliseconds value. If you need to print the Date-Time in a different format and timezone, you will need to use a SimpleDateFormat with the desired format and the timezone set to the applicable one e.g.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDate = sdf.format(date);
System.out.println(strDate);
Output:
2021-06-01T15:49:45.198Z
Some other important notes:
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Most of the symbols that you have used in YYYY-MM-DDThh:mm:ss.sssZ are wrong. Check the description of the symbols from the documentation pages of DateTimeFormatter and SimpleDateFormat.
* 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.
This question already has answers here:
Calendar returns date in wrong time zone
(5 answers)
DateFormat parse - not return date in UTC
(1 answer)
How to Parse Date from GMT TimeZone to IST TimeZone and Vice Versa in android
(4 answers)
Closed 4 years ago.
Here the that problem that i'm facing is -
First i have created a date object which will give me current date and time with device timezone i.e
Date date = new Date(); // Let say the time zone is India - GMT (+05:30)
The value of date is = "Mon Sep 24 13:54:06 GMT+05:30 2018"
No i have a Date formatter using which i have converted the following date object.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss z");
sdf.setTimeZone(TimeZone.getTimeZone(loadPreferences(Utility.TIMEZONE_NAME)));
// Here the timezone is Hawaii (GMT-10:00)
Now getting the time as per the new time zone i.e., Hawaii
String dateS = sdf.format(date);
// This will give you the date with new timezone - "2018/09/23 22:24:06 GMT-10:00"
Now converting this string date to date object as -
Date newDate = sdf.parse(dateS);
Now the new date which i'm getting is not as per the timezone which i have passed.
The value of newDate which i'm getting is = "Mon Sep 24 13:54:06 GMT+05:30 2018"
//This is device timezone not the one i have set.
I have already tried "Z", "z", "X", "ZZ", "ZZZZZ" in the date formatter still no luck.
If any of you have any idea reading this then let me know.
Two messages:
Your expectations are wrong. A Date hasn’t got a time zone, it cannot have. So what you are trying to obtain is impossible using Date and SimpleDateFormat no matter how you write the code.
The classes Date, SimpleDateFormat and TimeZone are long outdated and poorly designed. Their modern replacements are in java.time, the date and time API introduced in 2014.
ZonedDateTime
A modern ZonedDateTime has a time zone as the name says:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss z", Locale.US);
ZonedDateTime nowInHawaii = ZonedDateTime.now(ZoneId.of("Pacific/Honolulu"));
String dateS = nowInHawaii.format(formatter);
System.out.println(dateS);
Output from this snippet was:
2018/09/24 18:43:19 HST
If you want the offset in the output, change the formatter thusly:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss OOOO", Locale.US);
2018/09/24 18:45:53 GMT-10:00
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on new Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310, where the modern API was first described).
On (older) Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. Make sure you import the date and time classes from package org.threeten.bp and subpackages.
Links
Oracle tutorial: Date Time, explaining how to use java.time.
ThreeTen Backport project
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Java Specification Request (JSR) 310.
Please try to debug the value that is coming from
'loadPreferences(Utility.TIMEZONE_NAME)' and make sure it is same as "US/Hawaii"
Also try to debug by using this -
sdf.setTimeZone(TimeZone.getTimeZone("US/Hawaii"));
I have a timestamp 2018-01-01 18:20:23.11 which is in UTC. I need to print this in a different format but retain the UTC timezone. However if I use SimpleDateFormat ("dd MMM YYYY yyyy kk:mm z"), it takes my current timezone and gives me 01 Jan 2018 18:20 EST. I want this to print 01 Jan 2018 18:20 UTC. Doing a Timezone.getTimeZone("UTC") converts this time to UTC (does a +4 to hours)which is not the desired result.
DateTimeFormatter originalFormatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SS");
DateTimeFormatter newFormatter
= DateTimeFormatter.ofPattern("dd MMM uuuu HH:mm z", Locale.ENGLISH);
String originalTimestamp = "2018-01-01 18:20:23.11";
String differentFormat = LocalDateTime.parse(originalTimestamp, originalFormatter)
.atZone(ZoneId.of("Etc/UTC"))
.format(newFormatter);
System.out.println(differentFormat);
This prints
01 Jan 2018 18:20 UTC
ZoneId.of("Etc/UTC") or ZoneOffset.UTC?
A possibly nerdy edit: I had first written .atZone(ZoneOffset.UTC) in the conversion. I usually use ZoneOffset.UTC to denote UTC and consider this the nice and idiomatic way of specifying it. However in the case of your code, this resulted in the zone being given as Z in the output where you had asked for UTC. Using ZoneId.of("Etc/UTC") instead gives you what you want. I can find no other way of making sure that the zone is formatted as UTC (save hardcoding UTC in the format pattern string, but that would be an ugly hack).
BTW ZoneId.of("Etc/UTC").normalized() returns ZoneOffset.UTC (at least on my Java 10, but I expect it to be the case always).
SimpleDateFormat vs. java.time
SimpleDateFormat is not only long outdated, it is also notoriously troublesome. I recommend you avoid it. It is correct, as you have observed, that it uses your JVM’s default time zone. There is a way to persuade it to do differently, but I would not bother.
java.time is the modern Java date and time API. It came out in 2014 as a replacement for the old and poorly designed date and time classes. IMHO it is so much nicer to work with.
Link: Oracle tutorial: Date Time explaining how to use java.time
How can I perform this conversion in Java?
Currently, I'm doing:
public static String formatDate(String strDateToFormat) {
try {
SimpleDateFormat sdfSource = new SimpleDateFormat("EEEE, MMMM DD, YYYY");
Date date = sdfSource.parse(strDateToFormat);
SimpleDateFormat sdfDestination = new SimpleDateFormat("yyyy-MM-dd");
return sdfDestination.format(date);
} catch (ParseException pe) {
System.err.println("Parse Exception : " + pe);
}
return null;
}
However, this results in an incorrect format. It gives me the following output:
Friday, February 1, 2013 > 2013-01-04
Thursday, January 31, 2013 > 2013-01-03
You're using DD in your parsing part, which is the day of year. You want dd instead. You also probably want yyyy (year) instead of YYYY (week year). (In most cases they're the same value, but not always.)
You're using DD in your parsing part, which is the day of year. You want dd instead.
Change also YYYY in yyyy.
You can find all patterns here.
http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Your code has got two major problems and the existing answers have already solved one of them. The second and even more dangerous problem is, not using Locale with SimpleDateFormat, which is a Locale-sensitive type. Since your Date-Time string is in English, make sure to use Locale.ENGLISH or some other English-Locale. So, a correct initialization would be:
SimpleDateFormat sdfSource = new SimpleDateFormat("EEEE, MMMM d, y", Locale.ENGLISH);
Check Never use SimpleDateFormat or DateTimeFormatter without a Locale to learn more about it. Also, notice a single d which, for parsing, can cater to both single-digit as well as double-digit representation of a day-of-month. Similarly, a single y can cater to both two-digit as well as four-digit representation of a year.
Switch to the modern Date-Time API
Note that the java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API* released with Java SE 8 in March 2014.
Solution using java.time, the modern Date-Time API
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String input = "Friday, February 1, 2013";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEEE, MMMM d, u", Locale.ENGLISH);
LocalDate date = LocalDate.parse(input, dtf);
System.out.println(date);
}
}
Output:
2013-02-01
ONLINE DEMO
Some notes:
Here, you can use y instead of u but I prefer u to y.
The LocalDate#toString gives you a String in [ISO-8601 format] which is the exact same format you are expecting. So, you do not need to format LocalDate explicitly to obtain a String in this format.
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.