SimpleDateFormat parsed from String is one day ahead [closed] - java

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 days ago.
Improve this question
I have the below Calendar object for NewYork timezone.
TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
Calendar calNewYork = Calendar.getInstance();
calNewYork.setTimeZone(timeZone);
Currently it is 13th Feb. I'm using the below code to construct the Date object for 13th Feb 4 pm.
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
dateFormat.setTimeZone(timeZone);
Date closingTime = dateFormat.parse("2023/02/13 16:00:00");
When I print closingTime it is "Tue Feb 14 02:30:00 IST 2023" in India Tz which translates to 14th Feb 4 pm NewYork time. Why did it bump the date by an extra day?

The reason the date got bumped by an extra day is because of the time zone difference between "America/New_York" and "IST" (Indian Standard Time). The time zone difference between the two is 10.5 hours. When you convert the time from one time zone to another, it may result in a change in the date. In your case, the time in New York is 4 PM on the 13th of February, but in India, it's already the next day (14th of February) due to the time zone difference, which is why the date got bumped by an extra day.
You can resolve this issue by using a time zone aware date format like the Java 8 date-time API (LocalDateTime, ZonedDateTime, etc.) instead of SimpleDateFormat, which is time zone unaware. That way, you can ensure that the date and time are always in the correct time zone, and you won't have to worry about date changes due to time zone differences.

(…) "Tue Feb 14 02:30:00 IST 2023" in India Tz (…) translates to 14th Feb 4 pm NewYork time.
It does not…
At that time "Asia/Kolkata" was 10:30h ahead of "America/New_York". You can see that if you carefully parse and format with SimpleDateFormats that have different TimeZones set and compare the output considering the getTime() method of the Date. It matters which zone is set in the SimpleDateFormat when you parse because your String does not provide a zone, the format assumes one.
See the following example…
public static void main(String[] args) throws ParseException {
// two time zones for parsing and formatting
TimeZone tzNY = TimeZone.getTimeZone("America/New_York");
TimeZone tzKol = TimeZone.getTimeZone("Asia/Kolkata");
// input format for New York
SimpleDateFormat nyFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
// set the corresponding time zone
nyFormat.setTimeZone(tzNY);
// input format for
SimpleDateFormat kolFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
// set the corresponding time zone
kolFormat.setTimeZone(tzKol);
/*
* parse the same values of date and time of day
* using the two different formats
* (this will lead to two different moments in time)
*/
Date ctNy = nyFormat.parse("2023/02/13 16:00:00");
Date ctKol = kolFormat.parse("2023/02/13 16:00:00");
// output format for New York
SimpleDateFormat outFormatNY = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss z yyyy",
Locale.ENGLISH
);
// set the corresponding time zone
outFormatNY.setTimeZone(tzNY);
// output format for Kolkata
SimpleDateFormat outFormatKol = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss z yyyy",
Locale.ENGLISH
);
// set the corresponding time zone
outFormatKol.setTimeZone(tzKol);
// print the results formatted in the different zones and their epoch millis
System.out.println(String.format("%28s | %13s | %-30s",
"America/New_York",
"Epoch Millis",
"Asia/Kolkata"));
System.out.println("—".repeat(75));
System.out.println(String.format("%28s | %13d | %-30s",
outFormatNY.format(ctNy),
ctNy.getTime(),
outFormatKol.format(ctNy)));
System.out.println(String.format("%28s | %13d | %-30s",
outFormatNY.format(ctKol),
ctKol.getTime(),
outFormatKol.format(ctKol)));
}
Output:
America/New_York | Epoch Millis | Asia/Kolkata
———————————————————————————————————————————————————————————————————————————
Mon Feb 13 16:00:00 EST 2023 | 1676322000000 | Tue Feb 14 02:30:00 IST 2023
Mon Feb 13 05:30:00 EST 2023 | 1676284200000 | Mon Feb 13 16:00:00 IST 2023
You can have that in a much more intuitive way if you switch to java.time…

Related

How to parse date with only month and year with SimpleDateFormat

I am working with expiration date of card. I have a API where I will get expiration date in "yyMM" format as "String". Here I am trying to use
SimpleDateFormat with TimeZone.getTimeZone("UTC")
So my code is like
String a= "2011";
SimpleDateFormat formatter = new SimpleDateFormat("yyMM");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = formatter.parse(a);
System.out.println(date);
Now problem is, when I am passing 2011 the out it gives is Sat Oct 31 17:00:00 PDT 2020
Here you can see I am passing 11 as month but it is converting it to Oct instead of Nov.
Why?
And what other options I can use to convert string with yyMM to Date with Timezone?
You should use the Java 8 YearMonth class.
String a = "2011";
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("yyMM");
YearMonth yearMonth = YearMonth.parse(a, inputFormat);
DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("MMMM yyyy");
System.out.println(yearMonth.format(outputFormat));
Output
November 2020
You parsed it fine, but it's printed in PDT, your local timezone.
Sat Oct 31 17:00:00 PDT 2020
Well, Date doesn't track timezones. The Calendar class does, which is internal to the formatter. But still, default print behavior is current timezone.
If you logically convert this output back to UTC, and it will be November 1 since PDT is UTC-7.
Basically, use java.time classes. See additional information here How can I get the current date and time in UTC or GMT in Java?

Conversion of string to date

I have a date in this format (Thu Feb 11 00:00:00 GMT 530 2016) which is a string and I want to convert this to a simple date format (dd/mm/yyyy).
I have used the below code but it does not work:
SimpleDateFormat fmt123 = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
try {
refDt = fmt123.parse(refDate);
logger.log(Level.SEVERE, "date after parsing "+refDt);
}
catch (ParseException e1) {
e1.printStackTrace();
}
It gives me the result of: Tue Feb 12 00:00:00 UTC 530
How can I convert this?
What you want to achieve is a two-step process.
Step 1 - Parsing existing string
You are very close, but as you've noticed the 530 part (I guess it is milliseconds) is parsed as year.
Use following code to create the instance of SimpleDateFormat used for parsing
new SimpleDateFormat("EEE MMM dd HH:mm:ss z SSS yyyy")
Step 2 - Formatting
Once you've parsed your date object, you'd need to present it to the user. Typically you would use new SimpleDateFormat("dd/MM/yyyy") and use it to output the date. This will use your local machine settings (such as timezone) to do the formatting. Usually it is sufficient.
But this is far more complex...
Timezones - the same time will mean a different date in different timezones. What is 2 AM, 11 Feb 2016 in Europe/Amsterdam is 8 PM, 10 Feb 2016 in America/Boston (or correct me if I am wrong).
Different calendar - you've probably already heart about Gregorian, Julian or Chinese calendar. The same time moment might have different days/month or year if expressed in different calendars. Fortunately majority of time we're talking about Gregorian calendar...
There is a very nice article Date and time in Java that describes the complexities in more details.
Poor Format
That String Thu Feb 11 00:00:00 GMT 530 2016 apparently has a bad format. I assume the 530 is an offset-from-UTC. But it lacks a + or -, a serious omission. Also, while not required, a padding zero on a single-digit hour of an offset is advised (05 rather than 5).
FYI, +05:30 is the time zone for two time zones, Asia/Kolkata and for Asia/Colombo. See this list. No time zone has an offset of -05:30.
I suspect this string may not actually be parseable as-is. You will need to manipulate the input string before attempting a parse. Something like the following, but your code will have to be more flexible if your input strings may vary.
String input = "Thu Feb 11 00:00:00 GMT 530 2016".replace ( "GMT 530" , "GMT+05:30" );
java.time
The Question and other Answers use the old outmoded date-time classes. Classes such as java.util.Date/.Calendar & java.text.SimpleDateFormat have been supplanted by the java.time framework built into Java 8 and later.
The formatter codes in java.time are a bit different than those of SimpleTextFormat. Be sure to read the doc.
String input = "Thu Feb 11 00:00:00 GMT 530 2016".replace ( "GMT 530" , "GMT+05:30" );
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "EEE MMM dd HH:mm:ss z uuuu" );
ZonedDateTime zdtGmt = ZonedDateTime.parse ( input , formatter );
ISO 8601
The java.time classes use ISO 8601 formats by default in their toString method implementations.
String output = zdtGmt.toString ();
Time Zone
Let’s adjust into the specific time zone of Asia/Kolkata rather than GMT. A time zone is an offset-from-UTC plus a set of past, present, and future adjustment rules for anomalies such as Daylight Saving Time.
ZonedDateTime zdtAsiaKolkata = zdtGmt.withZoneSameInstant ( ZoneId.of ( "Asia/Kolkata" ) );
Dump to console.
System.out.println ( "input: " + input + " | zdtGmt: " + zdtGmt + " | output: " + output + " | zdtAsiaKolkata: " + zdtAsiaKolkata );
input: Thu Feb 11 00:00:00 GMT+05:30 2016 | zdtGmt: 2016-02-11T00:00+05:30[GMT+05:30] | output: 2016-02-11T00:00+05:30[GMT+05:30] | zdtAsiaKolkata: 2016-02-11T00:00+05:30[Asia/Kolkata]
Your format here
SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
should match your input
"Thu Feb 11 00:00:00 GMT 530 2016"
As is mentioned in the comments this causes the parses to think 530 is the year and it ignores the rest.
See SimpleDateFormat for details.
SimpleDateFormat fmt123 = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");
try {
refDt = fmt123.parse(refDate);
logger.log(Level.SEVERE, "date after parsing "+refDt);
}
catch (ParseException e1) {
e1.printStackTrace();
}

how to check different date formats in java

I am getting different date formats below dd-MM-yyyy,dd/MM/yyyy,yyyy-MM-dd,yyyy/MM/dd
SimpleDateFormat sm1 = new SimpleDateFormat("dd-MM-yyyy");
String date = "01-12-2013";
System.out.println("Date 1 is "+sm1.parse(date));
date = "2013-12-01";
System.out.println("Date 1 is "+sm1.parse(date));
the same simple date format gives the below result eventhough date format is wrong(ie:-2013-12-01).Below the results.
Date 1 is Sun Dec 01 00:00:00 IST 2013
Date 1 is Sun Jun 05 00:00:00 IST 7
You need to setLenient(false) to make parse() method throw ParseException for unparsable case
I have tried Jigar Joshi's answer.
==========================code=======================================
SimpleDateFormat sm1 = new SimpleDateFormat("dd-MM-yyyy");
sm1.setLenient(false);
String date = "01-12-2013";
System.out.println("Date 1 is "+sm1.parse(date));
date = "2013-12-01";
System.out.println("Date 1 is "+sm1.parse(date));
=========================Result========================================
Date 1 is Sun Dec 01 00:00:00 CST 2013
Exception in thread "main" java.text.ParseException: Unparseable date: "2013-12-01"
at java.text.DateFormat.parse(DateFormat.java:337)
at workflow.Test.main(Test.java:14)
Your date format is dd-MM-yyyy. That means the parser is expecting some day, month, and year format.
From the SimpleDateFormat documentation: the number of pattern letters in a Number type formatter is the minimum. So, while 2013 wouldn't make sense in our mind, it fits within the formatter's bounds.
You have provided 2013-12-01 as to fit into that format. What it appears the formatter is doing is providing December 1 (insert timezone here), and then adding 2,013 days to it.
That turns out to be June 6, 7 AD. There's some wiggle room for your timezone (I'm not sure which of the five timezones IST represents is actually yours).
So, believe it or not...the formatter is correct. Be very careful as to what kind of format you specify or allow in your dates!
If you don't want that parsed, then specify setLenient(false) on your instance of sm1.

Calendar.getTime() not returning UTC date if TimeZone is defined

I have done this for my Calendar instance to return Date in UTC timezone:
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:SS Z");
TimeZone tz = TimeZoneUtil.getTimeZone(StringPool.UTC);
formatter.setTimeZone(tz);
Date dtStart = null;
Date dtEnd = null;
try{
dtStart = formatter.parse(formatter.format(startDate.getTime()));
dtEnd = formatter.parse(formatter.format(endDate.getTime()));
}catch (Exception e) {
e.getStackTrace();
}
It works fine till I format calendar timestamp to return a string date with required timezone but when I parse that string date to Date date, it again picks up local timezone?
I need to store Date object in UTC timezone.
Any help will be highly appreciated!
You can use this:
Date localTime = new Date();
//creating DateFormat for converting time from local timezone to GMT
DateFormat converter = new SimpleDateFormat("dd/MM/yyyy:HH:mm:ss");
//getting GMT timezone, you can get any timezone e.g. UTC
converter.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("local time : " + localTime);;
System.out.println("time in GMT : " + converter.format(localTime));
It will give:
local time: Fri Jun 21 11:55:00 UTC 2013
time in GMT : 21/06/2013:11:55:00
I hope it will help.
Cheers.
Date object in java will always store the values in the host machine (your system) time zone information.
This is from javadoc :
Although the Date class is intended to reflect coordinated universal time (UTC), it may not do so exactly, depending on the host environment of the Java Virtual Machine.
You should trying using Joda Time which is much advanced.
Instead of setting TimeZone in multiple places, it is a good idea to set timezone using -Duser.timezone=GMT or PST.
And, you can easily test how Java deals with timezone and getTime() ignores timezone with an actual example:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); // print with timezone
TimeZone timeZone = TimeZone.getTimeZone(ZoneId.of("GMT"));
TimeZone.setDefault(timeZone); // set system timezone as GMT
sdf.setTimeZone(timeZone); // formatter also has a timezone
Date date = new Date();
System.out.println(date); // system says GMT date
System.out.println(date.getTime()); // only prints time in milliseconds after January 1, 1970 00:00:00 GMT
System.out.println(sdf.format(date));
timeZone = TimeZone.getTimeZone(ZoneId.of("America/Los_Angeles"));
TimeZone.setDefault(timeZone); // set system timezone as GMT
sdf.setTimeZone(timeZone); // formatter also has a timezone
date = new Date();
System.out.println(date);
System.out.println(date.getTime()); // prints the same value as above, "not including timezone offset"
System.out.println(sdf.format(date));
// GMT and PDT times are same as getTime() only returns time in ms since UTC for the day ignoring timezone which is mostly used for formatting
Wed Mar 14 22:43:43 GMT 2018
1521067423108
2018-03-14T22:43:43+0000
Wed Mar 14 15:43:43 PDT 2018
1521067423125 // not includes timezone in getTime()
2018-03-14T15:43:43-0700 // formatting looks fine
The good explanation of why Date object taking Current time zone value ,
please refer this SO answer
EDIT.
here I am gonna add some important part of that answers.
java.util.Date is has no specific time zone, although its value is most commonly thought of in relation to UTC. What makes you think it's in local time?
To be precise: the value within a java.util.Date is the number of milliseconds since the Unix epoch, which occurred at midnight January 1st 1970, UTC. The same epoch could also be described in other time zones, but the traditional description is in terms of UTC. As it's a number of milliseconds since a fixed epoch, the value within java.util.Date is the same around the world at any particular instant, regardless of local time zone.

android convert unix time to utc date

I am a little confused with the unix time stamp conversion to java.util.Date involving the time zones.
I have a unix time stamp that is "1367832568". it is a UTC date (Mon May 06 17:29:28 GMT+00:00 2013). when i do following :
Date d = new Date(1367832568 * 1000);
it gives me Mon May 06 17:29:28 GMT+08:00 2013 which is not correct. it should give me:
Mon May 07 01:29:28 GMT+08:00 2013
because the unix time stamp is actually a UTC date. so this is confusing. what should i do to convert the UTC unix time stamp to correctly convert to a UTC Date object.
I'm not sure exactely how are you formatting your date object, but by setting the timezone to the dateformat object (to GMT) I'm able to get
Mon May 06 09:29:28 GMT 2013 AM
which is the same date you are looking for.
long time = 1367832568 * (long) 1000;
Date date = new Date(time);
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy a");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
Log.d("date", format.format(date));

Categories