Java SimpleDateFormat gives different time zone for different day - java

I had a strange behaviour when parsing dates. Given
DateFormat sdf= new SimpleDateFormat("dd/MM/yyyy");
sdf.parse("25/10/2014") returns 25 Oct 2014 00:00:00 BST
while
sdf.parse("27/10/2014") returns 27 Oct 2014 00:00:00 GMT
I figured out that's because of the Daylight Time change, but surely I would expect the same time zone to be returned by the same parser. Or am I wrong?

Per the Wikipedia article on British Summer Time
During British Summer Time (BST), civil time in the United Kingdom is advanced one hour forward of Greenwich Mean Time (GMT), so that evenings have more daylight and mornings have less
BST begins at 01:00 GMT on the last Sunday of March and ends at 01:00 GMT (02:00 BST) on the last Sunday of October.
The last Sunday of October 2014 was the 26th. So, the TimeZone changed from British Summer Time to GMT as observed in the UK.
The default TimeZone is your system TimeZone, so when that changes your parser will too.

From the documentation of SimpleDateFormat#parse(String ParsePosition):
The TimeZone value may be overwritten, depending on the given
pattern and the time zone value in text. Any TimeZone
value that has previously been set by a call to setTimeZone()
may need to be restored for further operations.
So: No, the parser does not always return the same time zone.

Related

Get CST current date at 00:00:00 time in java

I need the current date in following format at 00:00:00 CST time.
Like say current date is July 9 2021 Then I need that date along with 00:00:00 time.
Expected Output:
Fri Jul 09 00:00:00 CST 2021
Current code:
LocalDateTime date= LocalDateTime.now().with(LocalTime.MIN);
Date dayStart= Date.from(date.atZone(ZoneId.systemDefault()).toInstant());
Output of CurrentCode: Fri Jul 09 00:00:00 UTC 2021
Current code picking servertime /GMT which is 5hrs ahead of CST.
Example: 09AM GMT is 14 CST/2PM CST
I have tried to set calendar to 00:00:00 and setTimeZone to America/New_York. But while am returning output as calendar.getTime() give some other time rather than giving CST 00:00:00.
Tried : #scheduled(zone="America/New_york" ) --Not Working.
There are two good answers. My suggestion only differs in the detail (which is where the devil is, according to some).
First of all you should avoid using the Date class if you can. You are already using java.time, the modern Java date and time API, (LocalDateTime, LocalTime, ZoneId). You are getting all the functionality that you need from java.time. So I am assuming that you are only converting to Date because you need a Date for some legacy API that you cannot afford to upgrade to java.time just now.
Instant startOfDay = ZonedDateTime.now(ZoneId.systemDefault())
.truncatedTo(ChronoUnit.DAYS)
.toInstant();
Date oldfashionedDate = Date.from(startOfDay);
System.out.println(oldfashionedDate);
.truncatedTo(ChronoUnit.DAYS) throws away the time part of the ZonedDateTime, usually leaving us with 00:00:00 on the same day in the same time zone.
Edit:
I want America Chicago time CDT
Running the above code with the default time zone of the JVM set to America/Chicago gave:
Mon Jul 12 00:00:00 CDT 2021
Getting the right Date value and getting the expected printed output are two different things since Date.toString() picks the default time zone of the JVM and uses it for rendering the string to be returned. This behaviour may give surprises. There is no way to persuade Date.toString() to use a different time zone, so the above output only comes through setting the default time zone.
Original text: There are a lot of time zones referred to as CST and there’s no way I can be sure which one you intended (and i believe that the comments stating that America/New_York is not one of them are correct). However, the only one that I could persuade the old-fashioned Date class to abbreviate CST was China Standard Time. Running the above code in Asia/Shanghai time zone gave this output:
Sat Jul 10 00:00:00 CST 2021
It looks right to me. Since you asked your question it has become Saturday 10th in China Standard Time time zone.
Any time zone will work for getting the right Date value, the start of the day in that time zone. You also wanted an abbreviation of CST in the printed output. Time zones that did not work for this include:
Australia/Adelaide time zone. Output was Sat Jul 10 00:00:00 ACST 2021. So even though Australian Central Standard Time is sometimes abbreviated just CST, Date chose ACST.
America/Havana. Cuba uses Cuba Daylight Time at this time of year, so CDT is output.
America/Winnipeg and American/Chicago. North American Central Time uses daylight saving time too, so here too CDT is output.
In any case, you know which time zone you intended, so I am leaving to you to pick.
The easiest way to change the timezone is to use System.setProperty("user.timezone", "America/New_York"); in Java NOTE:: America/New_York is not CST
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
class DateAndTimeZoneFormatter {
public static void main(String[] args) {
System.setProperty("user.timezone", "America/New_York");
LocalDateTime date = LocalDateTime.now().with(LocalTime.MIN);
Date dayStart = Date.from(date.atZone(ZoneId.systemDefault()).toInstant());
System.out.println(dayStart);
}
}
You could try to use a ZonedDateTime with a specific ZoneId:
public static void main(String[] args) {
// define the zone to be used
ZoneId americaChicago = ZoneId.of("America/Chicago");
// then take the date of today
ZonedDateTime nowInChicago = ZonedDateTime.of(
LocalDate.now(), // today
LocalTime.MIN, // start of day
americaChicago // zone
);
// define an output format
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendPattern("EEE MMM dd HH:mm:ss")
.appendLiteral(' ')
.appendZoneText(TextStyle.SHORT)
.appendLiteral(' ')
.appendPattern("uuuu")
.toFormatter(Locale.ENGLISH);
// then print the formatted String representation
System.out.println(nowInChicago.format(dtf));
}
This outputs
Fri Jul 09 00:00:00 CDT 2021
Downsides:
this won't fully match your expected output due to CST not being applied because it is daylight saving time. Therefore, CDT will be the output.
taking a Date.from this ZonedDateTime.toInstant() will affect the values:
Applying these two lines
Date sameNowInChicago = Date.from(nowInChicago.toInstant());
System.out.println(sameNowInChicago);
will output
Fri Jul 09 07:00:00 CEST 2021
on my machine because it is configured to have a ZoneId.of("Europe/Berlin"), which will be taken into account when printing a java.util.Date.
CEST ⇒ Central European Summer Time.

Same unix timestamp in two regions which are in the same timezone has different result

This code convert datetime to unix timestamp, but I have different result when I check the result in Mexico_City and Chicago, which are in the same timezone.
The result is :
Friday April 03, 2020 08:45:18 (am) in time zone America/Mexico City (CST) and
Friday April 03, 2020 09:45:18 (am) in time zone America/Chicago (CDT)
How to solve this problem?
https://www.epochconverter.com/timezones?q=1585925118&tz=America%2FMexico_City
https://www.epochconverter.com/timezones?q=1585925118&tz=America%2FChicago
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
LocalDateTime dateTime = LocalDateTime.parse(2020-04-03 09:45:18, formatter);
ZoneId zoneId = ZoneId.of("CST", ZoneId.SHORT_IDS)
ZoneOffset zoneOffset = zoneId.getRules.getOffset(LocalDateTime.now)
ldt.toInstant(ZoneOffset.of(String.valueOf(zoneOffset))).toEpochMilli //1585925118000
Not the same time zone
Your results say it:
Friday April 03, 2020 08:45:18 (am) in time zone America/Mexico City
(CST) and
Friday April 03, 2020 09:45:18 (am) in time zone America/Chicago (CDT)
Two time zones are mentioned, not one: America/Mexico City and America/Chicago. Both time zones have the same standard offset from UTC, -06:00, and both use summer time (Daylight Saving Time, DST), yet they are different time zones.
Your results are correct
This year (2020) summer time began on March 8 in America/Chicago. So on your example date, April 3, summer time was observed. Summer time was not observed in America/Mexico_City on this day. There summer time did not begin until April 5. This difference explains why the time was 8:45 in Mexico and simultaneously was 9:45 in Chicago. Use the links at the bottom for verifying the dates of the summer time transitions in the two time zones.
What is a time zone?
A time zone, as the name says, is a zone on Earth, but the concept also comprises the historic, present and known future offsets from UTC observed by the people in that zone.
Every time zone has a unique ID in the region/city format that is also used in the output from the Epoch Converter that you have used.
CST is not a time zone. CST is an ambiguous abbreviation. As mentioned in the comment it may refer to Central Standard Time, Cuba Standard Time or China Standard Time. You intended Central Standard Time, but even that is ambiguous: it may refer to North American Central Standard Time or Australian Central Standard Time. And while North American Central Standard Time is unique, unambiguous, it is not a time zone. It is the time used in America/Chicago and America/Winnipeg time zones (and more time zones) during the relatively few months of the year where standard time is observed. The rest of the year the mentioned time zones use Central Daylight Time instead. But yes, CST is also used in Mexico City for some of the year.
In Java ZoneId.of("CST", ZoneId.SHORT_IDS) gives you America/Chicago time zone because SHORT_IDS is defined to do that. This definition is there for one purpose only: to give you a behaviour that is compatible with what the now long outdated TimeZone class would have given you. Unless CST is used in your program for historic reasons and cannot (easily) be abandoned, you should neither use this nor SHORT_IDS. Use ZoneId.of("America/Chicago") if this is the time zone you want.
Links
Time Change 2020 in Mexico
Clock Changes in Chicago, Illinois, USA
Time Zone Abbreviations – Worldwide List
List of tz database time zones

Java Date start epoch

The java.util.Date class is based on the number of seconds since 1 January 1970 00:00 GMT. So why does this code
System.out.println(new Date(0));
print Thu Jan 01 01:00:00 GMT 1970? My local time zone is GMT, so I expected it to print 00:00:00 GMT.
There is an interesting reason for this. Refer (BST Offset bug report)
.
It says, "and the experiment with British Standard Time from 1968 to 1972, by which the time was advanced by one hour from GMT throughout the year." And further: “The local time produced by Date.toString() is historically correct, except for the time zone abbreviation. It should be "BST" (British Standard Time for this case), but it's a known limitation of the current TimeZone implementation.”
This link might help. I'm quite a novice at the Date class, but I figured this could help somehow.
Unix Epoch Time is a system of time describing how much time has elapsed since January 1st, 1970.
Therefore, when you create a new java.util.Date object with 0 milliseconds elapsed, it will return January 1st, 1970.
What you are looking for is here.

Java: What is the absolut first second in Calendar?

For example I have this:
Calendar result = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
result.setTime(new Date(0))
This should be the start of Calendar (1. Januar 1970 ...), but what is really the first second since epoche? Or more precise: What timezone with 0 milliseconds since epoche is the earliest?
Is it "Pacific/Kiritimati" the first?
To be precise UTC is not a timezone, it is a time standard. To be formally correct no country/territory is using UTC "timezone". But from a very basic view UTC is similar to GMT. So first second since epoche is one second after midnight in GMT (in 1.1.1970).
Also note, that countries that use GMT switch to different timezone when they apply daylight saving time. E.g. UK switches BST which is +01:00 from GMT

Discrepancy in Converting Date to TimeStamp in java

I have a Date Object in following:
Date date=new Date("Mon, 05 May 2014 12:31:12 +0000")
I want to get Timestamp of date Object then :
date.getTime()
1399293072000
but this value not correct , correct value in following :
1399276872000
//*** for get timestamp use of http://www.epochconverter.com ***\\
why ?
First things first, from the JavaDoc for Date
Date(String s)
Deprecated.
As of JDK version 1.1, replaced by DateFormat.parse(String s).
So the constructor you are using has been deprecated since 1997!
Next, onto the JavaDoc for Date.parse which the construtor uses:
It accepts many syntaxes; in particular, it recognizes the IETF
standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It also
understands the continental U.S. time-zone abbreviations, but for
general use, a time-zone offset should be used: "Sat, 12 Aug 1995
13:30:00 GMT+0430" (4 hours, 30 minutes west of the Greenwich
meridian). If no time zone is specified, the local time zone is
assumed. GMT and UTC are considered equivalent.
Empathsis mine.
So, what timezone are you in? Presumably not UTC.
You should specify local time zone while constructing Date object
Example:
Date date=new Date("Mon, 05 May 2014 12:31:12 GMT+0530");
Using Mon, 05 May 2014 12:31:12 +0000 at http://www.epochconverter.com I get 1399285872000 which is different from your timestamp.
Or you're passing different values, or there's a bug somewhere or
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
where the javadoc for java.util.Date.getTime() doesn't mention leap seconds.

Categories

Resources