Hi below is my code.
public class DateSample {
public static void main(String as[]){
Calendar c = Calendar.getInstance();
System.out.println("Curr : "+ c.getTime());
c.add(Calendar.DATE, -1);
c.set(Calendar.HOUR, 23);
c.set(Calendar.MINUTE, 59);
c.set(Calendar.SECOND, 59);
c.set(Calendar.MILLISECOND, 0);
System.out.println("aftr : "+c.getTime());
}
}
Output is :
Curr : Wed Feb 27 15:02:44 CET 2013
aftr : Wed Feb 27 11:59:59 CET 2013
The ouput what I want is Wed Feb 26 23:59:59 CET 2013. But why this confusion? Pleass help.
use Calendar.HOUR_OF_DAY
Field number for get and set indicating the hour of the day.
HOUR_OF_DAY is used for the 24-hour clock. E.g., at 10:04:15.250 PM
the HOUR_OF_DAY is 22.
c.set(Calendar.HOUR_OF_DAY, 23);
Related
Hi can any one explain why such abnormal behavior from Calendar .after method
Calendar cal = Calendar.getInstance();
Calendar cal1 = Calendar.getInstance();
cal.set(Calendar.HOUR, 14);
cal1.set(Calendar.HOUR, 13);
System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
cal.set(Calendar.DATE, Calendar.getInstance().get(Calendar.DATE));
System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
Output:
true Cal Tue Oct 01 02:55:16 IST 2019 cal1 Tue Oct 01 01:55:16 IST 2019
true Cal Wed Oct 30 02:55:16 IST 2019 cal1 Tue Oct 01 01:55:16 IST 2019
but I did not get why cal is after cal1 even if i have set cal1's date to current date,
so if cal is today, I assigned the time as 14 hr it mover to next date then i set the date as current date in cal while for cal1 i did not.
So why still cal.after(cal1) is showing true in second syso while my cal1 is clearly 1 day greater than cal?
any suggestion to resolve such problem? Use java.time
I agree with you that there are some surprises in your code. You may have intended this:
ZoneId zone = ZoneId.of("Asia/Kolkata");
ZonedDateTime zdt = ZonedDateTime.now(zone);
ZonedDateTime zdt1 = ZonedDateTime.now(zone);
zdt = zdt.withHour(14);
zdt1 = zdt1.withHour(13);
System.out.println(zdt.isAfter(zdt1) + " zdt " + zdt + " zdt1 " + zdt1);
zdt = zdt.withDayOfMonth(ZonedDateTime.now(zone).getDayOfMonth());
System.out.println(zdt.isAfter(zdt1) + " zdt " + zdt + " zdt1 " + zdt1);
Output when I ran the code just now:
true zdt 2019-09-30T14:44:13.630029+05:30[Asia/Kolkata] zdt1 2019-09-30T13:44:13.630362+05:30[Asia/Kolkata]
true zdt 2019-09-30T14:44:13.630029+05:30[Asia/Kolkata] zdt1 2019-09-30T13:44:13.630362+05:30[Asia/Kolkata]
I get true both times just as you got from your code, which shouldn’t be surprising. As others have said, 02:55h is after 01:55h, and Oct 30 is after Oct 01. Also, referring to my result, 14:44 is after 13:44. In both lines these two times are compared.
I am using java.time, the modern Java date and time API.
What went wrong in your code?
The surprises in your code stem from the Calendar class being poorly designed and often behaving differently from what we would immediately expect.
Why when you set the hour to 14, you get Tue Oct 01 02:55:16 IST 2019? The date has changed into the following month, and the hour of day is 2, not 14.
Why when you set the date to today’s date, September 30, you get October 30?
For 1., Calendar.HOUR refers to hour within AM or PM from 0 through 11. So setting it to 14 we should have expected an exception. A Calendar with standard settings doesn’t care. Since the time was already in PM, it extrapolates, so 14 PM becomes 2 AM on the next day. Since today is the last day of September, you get October 1.
For 2., Calendar.DATE doesn’t refer to the full date, but to the day of month. Since current day of month is 30 and we already had October1, we get October 30.
Long story short: Avoid the Calendar class. Use ZonedDateTime and/or other classes form java.time, the modern Java date and time API. They are so much nicer to work with and give far fewer surprises like the ones you experienced.
Link
Oracle tutorial: Date Time explaining how to use java.time.
Java docs for - Calendar.after()
public boolean after(Object when) {
return when instanceof Calendar && compareTo((Calendar)when) > 0;
}
//By definition :- true if the time of this Calendar is after the time represented by when; false otherwise.
System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
//true Cal Tue Oct 01 02:17:46 IST 2019 cal1 Tue Oct 01 01:17:46 IST 2019
cal.set(Calendar.HOUR, 13);
cal1.set(Calendar.HOUR, 14);
System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
//false Cal Tue Oct 01 01:16:55 IST 2019 cal1 Tue Oct 01 02:16:55 IST 2019
cal.set(Calendar.DATE, Calendar.getInstance().get(Calendar.DATE));
System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
//true Cal Wed Oct 30 13:17:46 IST 2019 cal1 Tue Oct 01 14:17:46 IST 2019
System.out.println(cal.after(cal1)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
//true Cal Tue Oct 01 02:25:19 MMT 2019 cal1 Tue Oct 01 01:25:19 MMT 2019
cal.set(Calendar.DATE, Calendar.getInstance().get(Calendar.DATE));
System.out.println(cal1.after(cal)+" Cal "+cal.getTime()+" cal1 "+cal1.getTime());
//false Cal Wed Oct 30 02:25:19 MMT 2019 cal1 Tue Oct 01 01:25:19 MMT 2019
Using
cal.setTime((Calendar.getInstance()).getTime());
instead of
cal.set(Calendar.DATE, Calendar.getInstance().get(Calendar.DATE));
gives the desired result.
I just found a strange behavior with the JAVA Calendar Class.
When I set the minutes to 0 the result differs depending on the used TimeZone.
Does anyone know why?
Example Code
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class CalendarTest {
public static void main(String[] args) {
Date date = new Timestamp(1477780200000L);
System.out.println(date); // 2016-10-30 00:30:00.0
testMethod(date, Calendar.getInstance(TimeZone.getTimeZone("CET"))); // Sun Oct 30 02:00:00 CET 2016
testMethod(date, Calendar.getInstance(TimeZone.getTimeZone("GMT+1"))); // Sun Oct 30 02:00:00 CEST 2016
}
private static void testMethod(Date date, Calendar c) {
c.setTime(date);
c.add(Calendar.HOUR_OF_DAY, 2);
c.set(Calendar.MINUTE, 0);
System.out.println(c.getTime());
}
}
edit (to make my question more understandable):
changed testMethod
this changed Method calculates in BOTH(!) cases Sun Oct 30 02:30:00 CEST 2016.
private static void testMethod(Date date, Calendar c) {
c.setTime(date);
c.add(Calendar.HOUR_OF_DAY, 2);
System.out.println(c.getTime());
}
You can see in the example code below that displayed date is rather different than real time (in milliseconds). The problem is that Sun Oct 30 02:00:00 CET 2016 exists both in CET and CEST time zone. When switching CEST => CET you are going back one hour (producing hour overlap). For Calendar object, this is very tricky because you are expressing time change in the selected time zone. When you want to reset minutes in this very specific, Calendar have to discover in which time zone you are expressing the change.
I'm not 100% how Calendar is handling this but in first example CET, you specifically suggesting that you want to use CET. Therefore, when overlapping takes place Calendar can select your suggestion (CET). When you are using GMT to express it then Calendar have to pick one of the time zones CET or CEST and is selecting CEST.
public static void main(String[] args) {
Date date = new Timestamp(1477780200000L);
System.out.println(date); // 2016-10-30 00:30:00.0
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("CET"));
calendar.setTime(date);
print(1, calendar); // 1: Sun Oct 30 00:30:00 CEST 2016 | 1477780200000
calendar.add(Calendar.HOUR_OF_DAY, 2);
print(2, calendar); // 2: Sun Oct 30 02:30:00 CEST 2016 | 1477787400000
calendar.set(Calendar.MINUTE, 0); // minutes expressed in CET
print(3, calendar); // 3: Sun Oct 30 02:00:00 CET 2016 | 1477789200000
System.out.println("--");
calendar = Calendar.getInstance(TimeZone.getTimeZone("CET"));
calendar.setTime(date);
print(4, calendar); // 4: Sun Oct 30 00:30:00 CEST 2016 | 1477780200000
calendar.add(Calendar.HOUR_OF_DAY, 2);
print(5, calendar); // 5: Sun Oct 30 02:30:00 CEST 2016 | 1477787400000
calendar.set(Calendar.MINUTE, 0); // minutes expressed in CET
print(6, calendar); // 6: Sun Oct 30 02:00:00 CET 2016 | 1477789200000
System.out.println("--");
calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+1"));
calendar.setTime(date);
print(4, calendar); // 4: Sun Oct 30 00:30:00 CEST 2016 | 1477780200000
calendar.add(Calendar.HOUR_OF_DAY, 2);
print(5, calendar); // 5: Sun Oct 30 02:30:00 CEST 2016 | 1477787400000
calendar.set(Calendar.MINUTE, 0); // minutes expressed in GMT
print(6, calendar); // 6: Sun Oct 30 02:00:00 CEST 2016 | 1477785600000
}
private static void print(int prefix, Calendar calendar) {
System.out.println(prefix + ": " + calendar.getTime() + " | " + calendar.getTimeInMillis());
}
Update
What is more interesting is the Calendar method getTimeInMillis:
public long getTimeInMillis() {
if (!isTimeSet) {
updateTime();
}
return time;
}
As you can see time is updated when you are getting it! There is a flag isTimeSet which is set to false every time you use set method like calendar.set(Calendar.MINUTE, 0). It means that your time becomes invalid in terms of right timezone/epoch etc. This method just sets the given calendar field to the given value and that's it. Moreover, this method is not doing any additional checks if your setting is valid. add method, on the other hand, respects calendar rules and move your date gracefully.
To summarize. You are setting minutes to 0 which forces calendar to recalculate date. You were right, the set is the problematic one.
Recently New Zealand observed daylight saving on 27 sept 15.
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
sd.setTimeZone(TimeZone.getTimeZone("Pacific/Auckland"));
Date dateValue = sd.parse("2015-09-30");
System.out.println(dateValue); // prints "Tue Sep 29 07:00:00 EDT 2015" My local system timzone in EDT
dateValue = DateUtils.addDays(dateValue, -6); // 6 days back 24 Sep of Pacific/Auckland
System.out.println(dateValue); // prints "Tue Sep 23 07:00:00 EDT 2015"
The second print statement should print Tue Sep 29 08:00:00 EDT 2015, as Daylight Saving not is in effect.
The issue is before 27 Sep 15 NZ = UTC+12
and after NZ = UTC +13
So on date of 23 Sep It should have time 08:00:00 not 07:00:00
The problem is within DateUtils.addDays from Apache Commons: it is using a Calendar with the default timezone to add and subtract days instead of using a user-supplied timezone. You can see this in the source code of the method add: it calls Calendar.getInstance() and not Calendar.getInstance(someTimezone)
If you construct yourself the Calendar and set the correct timezone, the problem disappears:
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
sd.setTimeZone(TimeZone.getTimeZone("Pacific/Auckland"));
Date dateValue = sd.parse("2015-09-30");
System.out.println(dateValue); // prints "Tue Sep 29 13:00:00 CEST 2015"
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Pacific/Auckland")); // set correct timezone to calendar
calendar.setTime(dateValue);
calendar.add(Calendar.DAY_OF_MONTH, -6);
dateValue = calendar.getTime();
System.out.println(dateValue); // prints "Wed Sep 23 14:00:00 CEST 2015"
also i have used joda api to resolved this timezone issue.
org.joda.time.DateTimeZone timeZone = org.joda.time.DateTimeZone.forID( "Pacific/Auckland" );
DateTime currentDate= new DateTime( new Date(), timeZone );
DateTime dateValue = now.plusDays( -6 ); // prints Tue Sep 29 08:00:00 EDT 2015
I have a simple for my problem:
TimeZone fromTimeZone = TimeZone.getTimeZone("America/Santiago");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 45);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
System.out.println(calendar.getTime() + " |Mili: " + calendar.getTimeInMillis());
The output: (My timezone is ICT)
Wed Apr 01 19:45:00 ICT 2015 |Milisecond: 1427892300000
The problem is: The calendar return wrong time for this Timezone on DST day. The timezone "America/Santiago" should be UTC-3 for now (ref: http://www.timeanddate.com/worldclock/chile/santiago.) . It need to show:
Wed Apr 01 18:45:00 ICT 2015 |Milisecond: 1427888700000
You have not applied the timezone fromTimeZone to the calendar .
Using Calendar I can get the week, year and all details for the current day. How can I navigate to a particualr day in that week?
Say, calendar.get(Calendar.DAY_OF_WEEK); returns 3, which means a Tuesday. Now, I want to go to say Friday for that week or any other day in that week. How can I do that?
Thanks for your replies. I think I need to make the scenario more clear.
Basically, I am trying to disable email alerts in my system during specified period.
I get values like:
disableStart = "FRIDAY-19:00"
disableEnd = "SUNDAY-19:00"
Now, i need to verify if email should be sent at a particular time.
e.g. if today = Thursday any time, send email
but, if today = Saturday any time can't send as per values above.
If I understand correctly you can use the Calendar.set(Field, value) method.
SimpleDateFormat f = new SimpleDateFormat("dd-MM-yyyy");
Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.DAY_OF_WEEK));
System.out.println(f.format(c.getTime()));
c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
System.out.println(c.get(Calendar.DAY_OF_WEEK));
System.out.println(f.format(c.getTime()));
Produces the output
6
08-10-2010
3
05-10-2010
Calendar c = Calendar.getInstance();
Date date = new Date();
c.setTime(date);
System.out.println("Today: " + c.getTime());
c.setTime(date);
c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println("MONDAY: " + c.getTime());
c.setTime(date);
c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
System.out.println("TUESDAY: " + c.getTime());
c.setTime(date);
c.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
System.out.println("WEDNESDAY: " + c.getTime());
c.setTime(date);
c.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
System.out.println("THURSDAY: " + c.getTime());
c.setTime(date);
c.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
System.out.println("FRIDAY: " + c.getTime());
c.setTime(date);
c.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
System.out.println("SATURDAY: " + c.getTime());
c.setTime(date);
c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
System.out.println("SUNDAY: " + c.getTime());
Gives:
Today: Fri Oct 08 15:45:14 CEST 2010
MONDAY: Mon Oct 04 15:45:14 CEST 2010
TUESDAY: Tue Oct 05 15:45:14 CEST 2010
WEDNESDAY: Wed Oct 06 15:45:14 CEST 2010
THURSDAY: Thu Oct 07 15:45:14 CEST 2010
FRIDAY: Fri Oct 08 15:45:14 CEST 2010
SATURDAY: Sat Oct 09 15:45:14 CEST 2010
SUNDAY: Sun Oct 10 15:45:14 CEST 2010
Which seams to mean that, at least on my system, the weeks starts on monday.
cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
Thanks to Kevin and Maurice for the answers. They really gave me the start point.
I ended with this test code, in case it helps anyone.
private static Date getTimeForAnyDayInWeek(int nDay, int nHour, int nMin)
{
Calendar c = Calendar.getInstance();
c.setFirstDayOfWeek(Calendar.MONDAY);
Date date = Calendar.getInstance().getTime();
c.setTime(date);
c.set(Calendar.DAY_OF_WEEK, nDay);
c.set(Calendar.HOUR_OF_DAY, nHour);
c.set(Calendar.MINUTE, nMin);
return c.getTime();
}
public static void main(String[] args)
{
Date start = getTimeForAnyDayInWeek(6, 19, 00);
Date end = getTimeForAnyDayInWeek(8, 19, 00);
Date c = new Date();
if (start.before(c) && c.before(end))
System.out.println("BLOCK");
else
System.out.println("SEND");
}
Thanks,
Anubhav
This is a perfect example of why jodatime is so good, here is my similar code
DateTime dt = new DateTime(); //current datetime, jodatime format
DateTime fridayLastWeek = dt.minusWeeks(1).dayOfWeek().setCopy("Friday");
Date convertedtorubbishdateformat = fridayLastWeek.toDate();
I used to waste so much time witht he standard java date/calendar. Then i got jodatime, you wont regret, it apparently will be used as part of standard java in the future. I didn;t bother downlaoding the jar for for ages, I wish I had done, you won't regret it.