Can someone explain why or if this code is wrong?
// main
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
System.out.println(calendar.getTime());
calendar.add(Calendar.DATE, -1);
System.out.println(calendar.getTime());
calendar.set(Calendar.HOUR_OF_DAY, 0);
System.out.println(calendar.getTime());
It produces:
Fri Jan 28 15:27:35 EST 2011
Thu Jan 27 15:27:35 EST 2011
Wed Jan 26 19:27:35 EST 2011
Am I missing something obvious? I expect to see something like Thu Jan 27 00:27:35 EST 2011
Thanks.
You're printing it out in the default time zone, not UTC. Although your calendar knows the time zone you're interested in, the java.util.Date returned by getTime() doesn't... and Date.toString() uses the system time zone.
Given that you specified in the subject that you wanted 12am in UTC, why would you expect to see Thu Jan 27 00:27:35 EST 2011? EST isn't the same as UTC.
EDIT: As always, I'd just like to point out that Joda Time is generally a much nicer API to use for date/time arithmetic in Java. You're currently getting the right answer, but I'd still recommend moving to Joda :)
EST is UTC - 5 hours, so 19:27 EST corresponds to 00:27 UTC. It seems logical to me.
Use a date format with a UTC locale to display your calendars, instead of using your default locale.
For UTC calculations (only) you might find using long is simpler.
long time = System.currentTimeMillis();
// yesterday at 12:00:00.000 am.
long yesterday = (time / 86400000 - 1) * 86400000;
Related
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.
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.
I just want to create a method that sets the Date to time "23:59:59.999" of the same day. So I made this:
public static Date date235959(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.HOUR, 23);
c.set(Calendar.MINUTE, 59);
c.set(Calendar.SECOND, 59);
c.set(Calendar.MILLISECOND, 999);
//c.set(Calendar.AM_PM, Calendar.PM);
return c.getTime();
}
When I run:
Date d = new Date();
d=date235959(d);
System.out.println(d.toString());
d=date235959(d);
System.out.println(d.toString());
I expected
Tue Sep 17 23:59:59 BRT 2013
Tue Sep 17 23:59:59 BRT 2013
But the output was
Tue Sep 17 23:59:59 BRT 2013
Wed Sep 18 11:59:59 BRT 2013
Why is that happened and how can I fix it?
The Calendar.HOUR is used for the 12-hour clock, use Calendar.HOUR_OF_DAY instead or put correct value for 12-hour clock: c.set(Calendar.HOUR, 11);
Use JodaTime instead of Java Calendar. It is the way more user friendly.
All Joda Time date/time objects are built on top of a long timestamp, so it is cheap to create those objects from a long.
In Joda Time ver 2.1 creating a date/time object from date/time components (year, month, day, hour, min, sec) is ~3.5 time slower than
the same operation for JDK GregorianCalendar.
Date components addition/subtraction is 3.5 times slower in Joda Time rather than in GregorianCalendar. On the contrary, time
components operations are about the same 3.5 times faster than
GregorianCalendar implementation.
Date/time parsing is working at about the same speed as in JDK SimpleDateFormat. The advantage of Joda parsing is that creating a
parser – DateTimeFormatter object is extremely cheap, unlike an
expensive SimpleDateFormat, so you don’t have to cache parsers
anymore.
http://java-performance.info/joda-time-performance/
Given this code...
String date = "11:00 AM";
SimpleDateFormat sdf = new SimpleDateFormat("h:mm a");
sdf.setTimeZone(TimeZone.getTimeZone("US/Eastern")); // --> should be GMT-4
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
Date parse = sdf.parse(date); // -- gives Thu Jan 01 16:00:00 GMT 1970
Why does date parsing give me 16:00 and not 15:00?
You cannot use java.util.Date to store time only. It will assign the 1970 year, which in some cases is incorrect. I would recommend to use org.joda.time.LocalTime for it.
Take day light savings also into consideration. This should give you what you expect
sdf.setTimeZone(TimeZone.getTimeZone("EST5EDT"));
If you are not providing any date portion by default it will be assigned the default Epoche standard date(01 Jan 1970 00:00 Hours is called Epoche standard time and it is taken as standard to measure all the time related calculations as base time).
The getTime() method of java.util.Date class returns the total number of milliseconds between the given date(including time also) and Epoche standard( 01 Jan 1970 00:00 Hours).
Though you are not using getTime() method so it is irrelevant here.
So simply you are getting that time.
And according to GMT it is right.
I thinks it will help you.
I want to perform a date operation in my android app. What I want is to subtract two dates and get the result. But subtraction leads to the wrong result whenever I change the time zone to central daylight time.
I use the following code to find the difference between the two dates.
Long lDateDiff = dtCycleDay.getTime() - m_dtHistory[0].getTime();
lDateDiff = lDateDiff / (1000 * 60 * 60 * 24);
Here in m_dtHistory[0], the date stored is Thu Mar 01 00:00:00 CST 2012.
And in my dtCycleDay variable the date changes from Thu Mar 01 00:00:00 CST 2012, Thu Mar 02 00:00:00 CST 2012, Thu Mar 03 00:00:00 CST 2012... and so on.
Now up to Thu Mar 11 00:00:00 CST 2012, the subtraction result is fine, but when the date changes to Thu Mar 12 00:00:00 CDT 2012, the CST changes to CDT and it show wrong subtraction result.
Why this happens and these happen only when I change the time zone to Central Daylight Time or pacific Daylight Time.
What do you mean by the "wrong" subtraction result?
My guess is that the result is 23 hours or 25 hours- which is exactly what I'd expect when a daylight transition occurs, as the intervening day is longer or shorter in terms of elapsed time. The "longer" day won't be relevant when dividing by 24, but the shorter one will... you're assuming that every day has 24 hours, and that you can therefore count the number of days by dividing the elapsed milliseconds by "the number of milliseconds in 24 hours". That doesn't work due to varying day lengths.
Don't forget that a Date value is purely an instant in time. It doesn't know about calendars or time zones... if you want to know the difference in "local" dates and times (where midnight to midnight is always 24 hours), I'd suggest using Joda Time instead... Date and Calendar don't really do that for you.
If the real problem you're describing is the time zone changing at the wrong date, that's a different matter entirely, and could be due to various different causes. For one thing, you should show exactly which time zone you're talking about: the abbreviations are ambiguous, whereas the tzdb names (e.g. "Europe/Paris") aren't.