SimpleDateFormat results in incorrect time - java

I have the following code
protected void amethod1() {
String strDate = "Thu May 18 16:24:59 UTC 2017";
String dateFormatStr = "EEE MMM dd HH:mm:ss zzz yyyy";
DateFormat dateFormat = new SimpleDateFormat(dateFormatStr);
Date formattedDate = null;
try {
formattedDate = dateFormat.parse(strDate);
} catch (ParseException e) {
e.printStackTrace();
}
}
The resulting value of formattedDate is- "Thu May 18 11:24:59 CDT 2017" .
I am testing this code in Chicago and the local timezone is CDT.
I am not able to understand why the time value changes from 16:24:59 to 11:24:59 even though. Am I missing something in the defined format of the date?

Class Date doesn't contain any timezone at all. It's just a number of milliseconds since 01.01.1970 00:00:00 GMT. If you try to see, what formattedDate contains with System.out.println or debugger, you'll get formatted date for your local timezone. 11:24:59 CDT and 16:24:59 UTC are the same time, so result is correct.
Is java.util.Date using TimeZone?
It is better to use jodatime or Java 8 Time API in order to better manage time and timezones.

First, you are getting the correct time. When Daylight Savings Time is in use in Chicago (which it is on May 18), the time is 11:24:59 when it’s 16:24:59 in UTC. So your Date value represents the same point in time. This is all you can expect from a Date.
I understand that you want not just a point in time, but also the UTC time zone. Since Axel P has already recommended Java 8 date and time API, I just wanted to fill in the details:
DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern(dateFormatStr, Locale.US);
ZonedDateTime dateTime = ZonedDateTime.parse(strDate, parseFormatter);
The result is
2017-05-18T16:24:59Z[UTC]
If you always want the UTC time zone, the Instant class is just right for it, so you will probably want to convert to it:
Instant instant = dateTime.toInstant();
Instants are always in UTC, popularly speaking.

SimpleDateFormat myFmt=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date now=new Date();
System.out.println(myFmt.format(now));
I hope I can help you. If you can,please adopt.Thank you

The resulting value of formattedDate is- "Thu May 18 11:24:59 CDT 2017" . Why? because your time zone running -5 hour from UTC time you will find in below link wiki time zone abbreviations, if you want result in same timezone you need to specify timezone in formater Hope you get my concern
https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
public static void amethod1() {
String strDate = "Thu May 18 16:24:59 UTC 2017";
String dateFormatStr = "EEE MMM dd HH:mm:ss zzz yyyy";
SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatStr);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date formattedDate = null;
try {
formattedDate = dateFormat.parse(strDate);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("formattedDate: "+dateFormat.format(formattedDate));
}

You specified timezone, that's why after parsing time on current timezone (where you are), SimpleDateFormat sets UTC timezone. When you try to output your date, it is displayed on your current timezone

It appears you would need to specify the TimeZone as well when you format the Date For eg. .TimeZone.setDefault(TimeZone.getTimeZone("PST"));
Have a look at this discussion TimeZone

The output of a Date depends on the format specified, where you can specify the timezone, as shown in the example below:
protected void amethod2() {
String strDate = "Thu May 18 16:24:59 UTC 2017";
String dateFormatStr = "EEE MMM dd HH:mm:ss zzz yyyy";
DateFormat dateFormat = new SimpleDateFormat(dateFormatStr);
Date formattedDate = null;
try {
formattedDate = dateFormat.parse(strDate);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("Date: " + formattedDate);
// Thu May 18 17:24:59 BST 2017, BST is my system default timezone
// Set the time zone to UTC for the calendar of dateFormat
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("Date in timezone UTC: " + dateFormat.format(formattedDate));
// Thu May 18 16:24:59 UTC 2017
// Set the time zone to America/Chicago
dateFormat.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
System.out.println("Date in timezone America/Chicago: " + dateFormat.format(formattedDate));
// Thu May 18 11:24:59 CDT 2017
}
As for the IDs, such as "UTC" and "America/Chicago" in the example, you can get a complete list of them via TimeZone.getAvailableIDs(). You can print them out to have a look:
Arrays.stream(java.util.TimeZone.getAvailableIDs()).forEach(System.out::println);
And you'll have:
Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
Africa/Algiers
Africa/Asmara
Africa/Asmera
Africa/Bamako
Africa/Bangui
Africa/Banjul
Africa/Bissau
Africa/Blantyre
...

Related

Java Date Time conversion to given timezone

I have a DateTime in the format of Tue, 30 Apr 2019 16:00:00 +0800 which is RFC 2822 formatted date
I need to convert this to the given timezone in the DateTime which is +0800
So if i summarized,
DateGiven = Tue, 30 Apr 2019 16:00:00 +0800
DateWanted = 01-05-2019 00:00:00
How can i achieve this in Java?
I have tried the below code but it gives 08 hours lesser than the current time which is
30-04-2019 08:00:00
Code i tried
String pattern = "EEE, dd MMM yyyy HH:mm:ss Z";
SimpleDateFormat format = new SimpleDateFormat(pattern);
Date startDate = format.parse(programmeDetails.get("startdate").toString());
//Local time zone
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
//Time in GMT
Date dttt= dateFormatLocal.parse( dateFormatGmt.format(startDate) );
You are on right approach but just use java-8 date time API module, first create DateTimeFormatter with the input format representation
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss Z");
And then use OffsetDateTime to parse string with offset
OffsetDateTime dateTime = OffsetDateTime.parse("Tue, 30 Apr 2019 16:00:00 +0800",formatter);
And the call the toLocalDateTime() method to get the local time
LocalDateTime localDateTime = dateTime.toLocalDateTime(); //2019-04-30T16:00
If you want the output in particular format again you can use DateTimeFormatter
localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) //2019-04-30T16:00:00
Note : As #Ole V.V pointed in comment, after parsing the input string into util.Date you are getting the UTC time
The class Date represents a specific instant in time, with millisecond precision.
So now if you convert the parsed date time into UTC you get 2019-04-30T08:00Z without offset, so you can use withOffsetSameInstant to convert it into any particular timezone
dateTime.withOffsetSameInstant(ZoneOffset.UTC)
You misunderstood. According to RFC 2822 +0800 means that an offset of 8 hours 0 minutes has already been applied to the time compared to UTC. So the output you got was the correct GMT time.
java.time
I recommend you skip the old and outdated classes SimpleDateFOrmat and Date. It’s much nicer to work with java.time, the modern Java date and time API. Furthermore it has the RFC format built in, so we don’t need to write our own formatter.
OffsetDateTime parsedDateTime = OffsetDateTime
.parse("Tue, 30 Apr 2019 16:00:00 +0800",
DateTimeFormatter.RFC_1123_DATE_TIME);
ZonedDateTime dateTimeInSingapore
= parsedDateTime.atZoneSameInstant(ZoneId.of("Asia/Singapore"));
System.out.println("In Singapore: " + dateTimeInSingapore);
OffsetDateTime dateTimeInGmt
= parsedDateTime.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println("In GMT: " + dateTimeInGmt);
Output:
In Singapore: 2019-04-30T16:00+08:00[Asia/Singapore]
In GMT: 2019-04-30T08:00Z
The built-in formatter is named RFC_1123_DATE_TIME because the same format is used in multiple Requests for Comments (RFCs).
Links
RFC 2822 Internet Message Format
Oracle tutorial: Date Time explaining how to use java.time.
with the help of #ole v.v's explanation i have separated the datetime value for two
1. time
2. timezone
then i used this coding to extract the datetime which is related to the given timezone
//convert datetime to give timezone
private static String DateTimeConverter (String timeVal, String timeZone)
{
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat offsetDateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
offsetDateFormat2.setTimeZone(TimeZone.getTimeZone(timeZone));
String result =null;
try {
result = offsetDateFormat2.format(format.parse(timeVal));
} catch (java.text.ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}

SimpleDateFormat parse not honouring timezone

public static void main(String[] args) throws ParseException {
SimpleDateFormat dt = new SimpleDateFormat("MM dd yy");
dt.setLenient(false);
dt.setTimeZone(TimeZone.getTimeZone("Asia/Hong_Kong"));
Date date = dt.parse("05 14 16");
System.out.println(date);
}
Output: Fri May 13 21:30:00 IST 2016
If i try to use the output it is switching to one day before instead of the correct day.
Is this expected or an issue with the API?
This is expected and there is no bug in Java.
Class Date does not contain timezone information. A java.util.Date is nothing more than wrapper for a number of milliseconds since 01-01-1970, 00:00:00 GMT. It does not remember that the string that it was parsed from contained information about a timezone.
When you display a Date, for example by (implicitly) calling toString() on it as you are doing here:
System.out.println(date);
it will be printed in the default timezone of your system, which is IST in your case.
If you want to print it in a certain timezone, then format it using a SimpleDateFormat object, setting the desired timezone on the SimpleDateFormat object. For example:
DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss Z");
df..setTimeZone(TimeZone.getTimeZone("Asia/Hong_Kong"));
System.out.println(df.format(date));

Convert UTC Date to local Date

I am converting from epoch time (which is in UTC) to a format as shown below. Now I tried different SO answers to convert UTCDate from UTC to local time. But I am not getting the local time.
Any help would be appreciated.
String epochTime = "1436831775043";
Date UTCDate = new Date(Long.parseLong(epochTime));
Date localDate; // How to get this?
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("h:mm a");
String result = simpleDateFormat.format(UTCDate);
Also, the conversion has to be done without the help of any external library.
Java 8
String epochTime = "1436831775043";
Instant utcInstant = new Date(Long.parseLong(epochTime)).toInstant();
ZonedDateTime there = ZonedDateTime.ofInstant(utcInstant, ZoneId.of("UTC"));
System.out.println(utcInstant);
LocalDateTime here = there.withZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(here);
Which outputs:
2015-07-13T23:56:15.043Z
2015-07-14T09:56:15.043
After thoughts...
I think you're chasing your tail. Date is just a container for the number of milliseconds since the epoch (January 1, 1970, 00:00:00 GMT). It doesn't internally carry a representation of a time zone (AFAIK).
For example...
String epochTime = "1436831775043";
Date UTCDate = new Date(Long.parseLong(epochTime));
// Prints the "representation" of the Date
System.out.println(UTCDate);
// Local date/time format...
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy h:mm:ss a");
try {
System.out.println("local format: " + simpleDateFormat.format(UTCDate));
System.out.println("local Date: " + simpleDateFormat.parse(simpleDateFormat.format(UTCDate)));
} catch (ParseException ex) {
Logger.getLogger(JavaApplication203.class.getName()).log(Level.SEVERE, null, ex);
}
// UTC date/time format
try {
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("utc format: " + simpleDateFormat.format(UTCDate));
System.out.println("utc date: " + simpleDateFormat.parse(simpleDateFormat.format(UTCDate)));
} catch (ParseException ex) {
Logger.getLogger(JavaApplication203.class.getName()).log(Level.SEVERE, null, ex);
}
Which outputs...
Tue Jul 14 09:56:15 EST 2015
local format: 14/07/2015 9:56:15 AM
local Date: Tue Jul 14 09:56:15 EST 2015
utc format: 13/07/2015 11:56:15 PM
utc date: Tue Jul 14 09:56:15 EST 2015
If you have a look at local Date and utc date they are the same thing, even though the local format and utc format are formatted correctly.
So, instead of chasing your tale trying to get Date to "represent" a value you want, either use Java 8's Time API or JodaTime to manage the Time Zone information or simply format the Date into the Time Zone you want...
Further, if we do something like...
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy h:mm:ss a");
Date localDate = simpleDateFormat.parse(simpleDateFormat.format(UTCDate));
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date utcDate = simpleDateFormat.parse(simpleDateFormat.format(UTCDate));
System.out.println(localDate.getTime());
System.out.println(utcDate.getTime());
System.out.println(localDate.equals(utcDate));
It will print...
1436831775000
1436831775000
true
You can set your time zone in the formatter:
simpleDateFormat.setTimeZone(TimeZone.getDefault());

Get the time of other TimeZone by date string, the result is wrong

I only have a date string, and I want to see the time in other TimeZone by it. So I did it like that:
String dateStr = "2014-05-15 16:14:58 PM";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
sdf.setTimeZone(TimeZone.getTimeZone("America/Denver"));
Date date = sdf.parse(dateStr);
System.out.println(date);
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
System.out.println(sdf1.format(date));
This is the current TimeZone in my computer:
The result that the code ran was that:
Fri May 16 06:14:58 CST 2014
2014-05-16 06:14:58 AM
The result is wrong, I had the right result by changing the TimeZone to "America/Denver" in my computer, and I saw that:
America/Denver —— 2014-05-15 02:14:58 AM
I don't know why it likes that?
But if I had a Date not a date String, I do that :
public static String getFormatedDateString(String _timeZone) {
TimeZone timeZone = null;
if (StringUtils.isEmpty(_timeZone)) {
timeZone = TimeZone.getDefault();
} else {
timeZone = TimeZone.getTimeZone(_timeZone);
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
sdf.setTimeZone(timeZone);
// TimeZone.setDefault(timeZone);
return sdf.format(new Date());
}
System.out.println("America/Denver —— " + getFormatedDateString("America/Denver"));
The result likes that:
------Asia/Shanghai------
2014-05-15 16:32:04 PM (current date)
America/Denver —— 2014-05-15 02:32:04 AM
This result is right.
So I was confused, I could't find the problem when I just have a date string and I want to know the time of other TimeZone. Could any body help me?
Date object in Java is independent of the concept of timezone.
What you want to do get the equivalent time in another timezone of a date string which is 'supposed' to be in your own timezone.
However, 2nd point appears backwards in your code:
String dateStr = "2014-05-15 16:14:58 PM";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
sdf.setTimeZone(TimeZone.getTimeZone("America/Denver"));
Date date = sdf.parse(dateStr);
What these 4 lines do is consider the date string as a point in time in "America/Denver" timezone.
When you parse it to the date object, it would give you the equivalent time in your own timezone.
You want it the other way round:
Hence staying close to your code (you can just use a single SimpleDateFormat instance effectively, which you can figure out later),
Drop the setTimezone on the first sdf:
String dateStr = "2014-05-15 16:14:58 PM";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
//sdf.setTimeZone(TimeZone.getTimeZone("America/Denver"));
Date date = sdf.parse(dateStr);
System.out.println(date);
Add the same setTimezone to the other sdf:
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
sdf1.setTimeZone(TimeZone.getTimeZone("America/Denver"));
System.out.println(sdf1.format(date));
Now, you are parsing your date String to a date in your current (JVM's) timezone. Then format the same date to a different timezone's String.
Output I get with the changed code (my JVM's timezone being IST):
Thu May 15 16:14:58 IST 2014 // Parsed the date string in IST
2014-05-15 04:44:58 AM // Equivalent time in Denver

I am getting java.text.ParseException

In the below code getting parsing error:please help.
DateFormat converter = new SimpleDateFormat("dd/MM/yyyy:HH:mm:ss");
converter.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat formatter = new SimpleDateFormat("E, MMM dd yyyy");
Date date = formatter.parse(converter.format(new Date()));
I will try to explain what JB Nizet and others tried in the comments. In a simplified manner to make it understandable.
A Date is nothing else but a long which represents the time since epoch and a nice toString() method. Basically.
So if you create a Date date = new Date(); it sets the date's time value to System.currentTimeMillis();, nothing more, nothing less.
The interesting thing is that the Unix time is already "in UTC (=GMT)", if you want to say so.
If you now print the date like this
Date date = new Date();
System.out.println(date);
you implicitly call date.toString();.
This toString() can be seen as follows:
public String toString() {
return new SimpleDateFormat("E MMM dd HH:mm:ss z YYYY").format(this);
}
The SimpleDateFormat uses by default YOUR timezone. But it doesn't change the value of the date at all, it just prints it in another way.
If you now want to see the date in GMT you can simply set the SimpleDateFormat yourself:
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("E MMM dd HH:mm:ss z YYYY");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf.format(date));
To push it further you could now write a simple static method somewhere to print dates in specific timezones:
public static void printDate(Date date) {
printDate(date, "GMT");
}
public static void printDate(Date date, String timeZone) {
printDate(date, TimeZone.getTimeZone(timeZone));
}
public static void printDate(Date date, TimeZone timeZone) {
SimpleDateFormat sdf = new SimpleDateFormat("E MMM dd HH:mm:ss z YYYY");
sdf.setTimeZone(timeZone);
System.out.println(sdf.format(date));
}
To see what we all are talking about (that the timestamp does never change) you can print both:
public static void printDate(Date date, TimeZone timeZone) {
SimpleDateFormat sdf = new SimpleDateFormat("E MMM dd HH:mm:ss z YYYY");
sdf.setTimeZone(timeZone);
System.out.println(sdf.format(date) + " has the timestamp " + date.getTime());
}
If we now do some simple tests we see these results:
Local Time:
Sat Feb 22 16:08:12 CET 2014 has the timestamp 1393081692749
GMT:
Sat Feb 22 15:08:12 GMT 2014 has the timestamp 1393081692749
PST:
Sat Feb 22 07:08:12 PST 2014 has the timestamp 1393081692749
As you can see the times are all correct for their timezones, and the timestamp itself is always the same.
So to answer your question: Your simple new Date();, as it's already written in the comments, already achieves what you want: the Date is always in UTC (which equals GMT).

Categories