I'm trying to get the date and time of the first day of the prior month; specifically as it is January I'm trying to get: Sun Dec 01 00:00:00 EST 2013. I am using the below code snippet which I have modified from another found here on Stackoverflow while researching this subject; this code snippet will return: Sun Dec 01 12:00:00 EST 2013. I do not understand why setting the minimum hour for the 1st in fact returns noon.
Calendar aCalendar = Calendar.getInstance();
// add -1 month to current month
aCalendar.add(Calendar.MONTH, -1);
// set DATE to 1, so first date of previous month
//aCalendar.set(Calendar.DATE, 1);
aCalendar.set(Calendar.DATE, aCalendar.getActualMinimum(Calendar.DAY_OF_MONTH));
aCalendar.set(Calendar.HOUR, aCalendar.getActualMinimum(Calendar.HOUR));
aCalendar.set(Calendar.MINUTE, aCalendar.getActualMinimum(Calendar.MINUTE));
aCalendar.set(Calendar.SECOND, aCalendar.getActualMinimum(Calendar.SECOND));
Date firstDateOfPreviousMonth = aCalendar.getTime();
If I modify the following line as shown and set 0 I get the same result:
aCalendar.set(Calendar.HOUR, 0);
If I modify it as follows I get 1pm:
aCalendar.set(Calendar.HOUR, 0);
Result: Sun Dec 01 13:00:00 EST 2013
From the Java Docs
HOUR Field number for get and set indicating the hour of the morning
or afternoon.
You'll want to use HOUR_OF_DAY instead
HOUR_OF_DAY Field number for get and set indicating the hour of the
day.
Or set the AM_PM accordingly...
AM_PM Field number for get and set indicating whether the HOUR is
before or after noon.
In any case, take the time to consult the Java Docs
Some example code using Joda-Time 2.3.
Using default time zone, we create a DateTime instance of now (current moment), go back to previous month (in a smart manner, compensating for short month like February), get the first of month by asking for "minimum value", and then get first moment of that first-of-month day.
org.joda.time.DateTime startOfPreviousMonth = new org.joda.time.DateTime().minusMonths(1).dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
Note the method withTimeAtStartOfDay to get the first moment of the day. That moment may or may not be 00:00:00 in local time (because of Daylight Saving Time or other anomalies).
Using explicit time zone (almost always a better practice)…
DateTimeZone timeZone = DateTimeZone.forId( "Europe/Paris" ); // "Asia/Kolkata" etc.
org.joda.time.DateTime startOfPreviousMonth = new org.joda.time.DateTime( timeZone ).minusMonths(1).dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
Get a string…
String string = startOfPreviousMonth; // or startOfPreviousMonth.toString();
To convert back to a java.util.Date instance for communicating with other libraries…
java.util.Date date = startOfPreviousMonth.toDate();
Related
Simple question why the result is like the following for this code:
Calendar cal2 = Calendar.getInstance();
cal2.set(Calendar.HOUR, 12);
cal2.set(Calendar.AM_PM, Calendar.PM);
System.out.println(cal2.getTime().toString()); // Wed Jan 13 00:11:08 EET 2021
cal2.set(Calendar.AM_PM, Calendar.PM);
System.out.println(cal2.getTime().toString()); // Wed Jan 13 12:11:08 EET 2021
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR, 12);
cal.set(Calendar.AM_PM, Calendar.AM);
System.out.println(cal.getTime().toString()); // Tue Jan 12 12:11:08 EET 2021
cal.set(Calendar.AM_PM, Calendar.AM);
System.out.println(cal.getTime().toString()); // Tue Jan 12 00:11:08 EET 2021
The first looks like it is 12 at midnight not afternoon.
The third one looks like it is 12 afternoon, not midnight
Why setting calendar AM or PM multiple times change the result?
How to set the time correctly?
Calendar is very confusing
You are so far from the first being confused about how the Calendar class works. Fortunately the class is also long outdated. You should not use it.
Why setting calendar AM or PM multiple times change the result? …
To answer your question as asked, Andi80 is correct in the other answer and the comments to it: HOUR goes from 0 through 11. The documentation says about HOUR:
Field number for get and set indicating the hour of the morning or
afternoon. HOUR is used for the 12-hour clock (0 - 11). Noon and
midnight are represented by 0, not by 12. E.g., at 10:04:15.250 PM the
HOUR is 10.
When you first set hour to 12 and AM/PM to PM, one should have expected an exception because the hour value is out of range. But no, a Calendar object with default settings doesn’t give you that. Instead it sets the time to 0 AM the following day; Jan 13 when you ran the code on Jan 12. By Calendar logic hour 12 is the hour that comes after hour 11.
When you set PM again, Calendar takes off from the time you had already got, which is in AM, and changes it into PM, so you get 12:11:08, still on Jan 13, the following day.
Why does it calculate the time twice? Not once and not three times when you do three calls to set()? It’s another confusing trait of Calendar. It calculates the time when you call getTime() (and some designated other methods). At that point it picks up all the changes from the calls to set() up to that point and combines them to the best of its abilities, discarding some if there are conflicts, using rules that no person in their right mind will want to understand.
The case for AM is similar, so I leave the details to the reader.
java.time
… How to set the time correctly?
I recommend that you use java.time, the modern Java date and time API, for your time work. If you just want 12 noon or 12 midnight, they are built in as constants:
LocalTime t12Noon = LocalTime.NOON;
System.out.println(t12Noon);
LocalTime t12Midnight = LocalTime.MIDNIGHT;
System.out.println(t12Midnight);
Output is:
12:00
00:00
A LocalTime is a time of day without a date.
If you have already got a time and only want to adjust the hour and AM/PM, use with():
LocalTime t12Noon = LocalTime.now(ZoneId.systemDefault())
.with(ChronoField.CLOCK_HOUR_OF_AMPM, 12)
.with(ChronoField.AMPM_OF_DAY, 1); // 1 = PM
System.out.println(t12Noon);
LocalTime t12Midnight = LocalTime.now(ZoneId.systemDefault())
.with(ChronoField.CLOCK_HOUR_OF_AMPM, 12)
.with(ChronoField.AMPM_OF_DAY, 0); // 0 = AM
System.out.println(t12Midnight);
12:47:00.665155
00:47:00.669248
If you need the date too, use ZonedDateTime or another appropriate class. All of the date-time classes of java.time that include time of day have the same with method, so the code will be the same.
If you indispensably need a Calendar object for a legacy API that you cannot afford to upgrade to java.time just now, use a ZonedDateTIme from java.time for your time math. Then use GregorianCalendar.from(ZoendDateTIme) for the conversion to a Calendar object.
Links
Documentation of Calendar.HOUR
Oracle tutorial: Date Time explaining how to use java.time.
Calendar.HOUR takes inputs in range 0-11. It will wrap around the 12 to a 0.
Use Calendar.HOUR_OF_DAY instead to use values from 0-23.
This is regarding Java Calendar and the effects we encountered after today day light saving change in Toronto.
Below is the code
Date date = new Date(); //Sun Mar 11 00:00:00 EST 2018
Integer time = 349;
Calendar scheduleDateCal = Calendar.getInstance();
scheduleDateCal.setTime(date);
scheduleDateCal.set(Calendar.MINUTE, 0);
scheduleDateCal.set(Calendar.HOUR_OF_DAY, 0);
String strSchAdminTime = String.valueOf(time);
Integer schAdminMinute = time;
if (strSchAdminTime.length() >= 2) {
schAdminMinute = Integer.valueOf(strSchAdminTime.substring(strSchAdminTime.length()-2));
}
if(time>60){
Integer schAdminHour = Integer.valueOf(strSchAdminTime.substring(0,strSchAdminTime.length()-2));
scheduleDateCal.add(Calendar.HOUR_OF_DAY, schAdminHour);
}else{
scheduleDateCal.add(Calendar.HOUR_OF_DAY, 0);
}
scheduleDateCal.add(Calendar.MINUTE, schAdminMinute);
System.out.println(scheduleDateCal.getTime());
I know this code hasn't done with the best practises however I need to maintain it for the current release. In here it uses integer to represent the time portion and later there is a logic to extract the hours and minutes from it.
When I followed the logic, the hour portion is 3. Then there is a logic to add this time to Calendar object with value 'Sun Mar 11 00:00:00 EST 2018' with below statement
scheduleDateCal.add(Calendar.HOUR_OF_DAY, schAdminHour);
Theoretically after this calculation, the calendar object should have value "Sun Mar 11 03:00:00 EDT 2018". However it returns "Sun Mar 11 04:00:00 EDT 2018" I know starting from today the time will go one hour ahead with the daylight saving. Can any one please help me to understand this
Appreciate the help.
At 00:00:00 today (Sunday March 11, 2018) summer time (DST) was not yet in effect, so that time was correctly rendered as Sun Mar 11 00:00:00 EST 2018 (EST for Eastern Standard Time). Date.toString chooses between EST and EDT based on the time contained in the Date object (not based on the time the toString method is called). When you add 3 hours to that time, you cross the time at 2 when the clock was turned forward to 3. So 3 hours after your start time the time is 04:00:00 EDT (EDT for Eastern Daylight Time).
PS Modern code
PS In case you or someone else is interested, here is the modern — both simpler and shorter — version of your code. To set the time to 03:49:
int time = 349;
ZoneId zone = ZoneId.of("America/Toronto");
ZonedDateTime scheduledDateTime = LocalDate.now(zone)
.atTime(time / 100, time % 100)
.atZone(zone);
System.out.println(scheduledDateTime);
Today this printed
2018-03-11T03:49-04:00[America/Toronto]
Still better, of course, if you can get completely rid of representing 03:49 as the integer value 349. To use your JVM’s time zone setting you may set zone to ZoneId.systemDefault(). This is fragile because the setting may be changed at any time by other parts of your program or other programs running in the same JVM.
To set the time to 3 hours 49 minutes after midnight (which with DST transition isn’t the same thing, as you have seen):
ZonedDateTime scheduledDateTime = LocalDate.now(zone)
.atStartOfDay(zone)
.plusHours(time / 100)
.plusMinutes(time % 100);
This time I got
2018-03-11T04:49-04:00[America/Toronto]
EST is -5, EDT is -4, so you get 1 hour when you are calling add().
You can use scheduleDateCal.set(Calendar.HOUR_OF_DAY, schAdminHour) and scheduleDateCal.set(Calendar.MINUTE, schAdminMinute), if you need result in different timezone.
I have a date in the string that looks like MON 07:15. I'm trying to parse this to a Date using this snippet of code:
System.out.println(new SimpleDateFormat("E kk:mm").parse("MON 07:15"));
Using the above code, prints a date that reads:
Mon Jan 05 07:15:00 EET 1970
I'd like the parse the date string to the next upcoming date. At the time of posting, my local date and time is Fri Aug 08 11:45:00 EEST 2014 and the next Monday will be on the 11th so the resultant date that I'm looking for is Mon Aug 11 07:15:00 EEST 2014. How can I parse this?
The day and time object that I'll be parsing will always be in the future.
I would separate parsing from everything else.
Parse the value as you're already doing, which gives you a date in the wrong year.
From that, take the time of day and the day of week - those are the important things. You can throw everything else away.
Next, take the current date and time, and perform whatever operations you need to in order to get to the right date/time. You should consider:
What time zone are you interested in?
If the current time is 06:00 on a Monday and you've been asked for 07:15 on a Monday, does that mean today or next Monday?
If the current time is 08:00 on a Monday and you've been asked for 07:15 on a Monday, does that mean today or next Monday?
By separating out the parsing from the computations, you can make the testing simpler two: test each of the operations separately. I'd advise using a clock abstraction of some kind to indicate "an object which can get you the current instant in time" - that way you can test all kinds of combinations of "desired day/time" and "current day/time".
Ideally, use java.time from Java 8 or Joda Time - both are much nicer than the java.util.* API.
Are you looking something like following?
DateFormat df = new SimpleDateFormat("E kk:mm");
Date date = df.parse("MON 07:15");
Date today = new Date();
Calendar calendar = Calendar.getInstance();
Calendar calendar1 = Calendar.getInstance();
calendar.setTime(today);
calendar1.setTime(date);
if (calendar.get(Calendar.DAY_OF_WEEK) == calendar1.get(Calendar.DAY_OF_WEEK)) {
String time = df.format(today);
Date t1 = df.parse(time);
if (t1.before(date)) {
calendar.set(Calendar.HOUR, calendar1.get(Calendar.HOUR));
calendar.set(Calendar.MINUTE, calendar1.get(Calendar.MINUTE));
calendar.set(Calendar.SECOND, 0);
System.out.println(calendar.getTime());
} else {
calendar.add(Calendar.DATE, 7);
calendar.set(Calendar.HOUR_OF_DAY, calendar1.get(Calendar.HOUR));
calendar.set(Calendar.MINUTE, calendar1.get(Calendar.MINUTE));
calendar.set(Calendar.SECOND, 0);
System.out.println(calendar.getTime());
}
} else {
int toDay = calendar.get(Calendar.DAY_OF_WEEK);
int givenDay = calendar1.get(Calendar.DAY_OF_WEEK);
int count = 7 - toDay + givenDay;
calendar.add(Calendar.DAY_OF_MONTH, count);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.HOUR_OF_DAY, calendar1.get(Calendar.HOUR));
calendar.set(Calendar.MINUTE, calendar1.get(Calendar.MINUTE));
System.out.println(calendar.getTime());
}
Out put:
Mon Aug 11 07:15:00 IST 2014
Leave me a comment telling me whether I got your question correct.
This answer addresses the second part, getting the next logical date from today.
Avoid .Date/.Calendar
The java.util.Date & .Calendar classes bundled with Java are notoriously troublesome. Avoid them.
Joda-Time or java.time
I suggest learning how to use a sophisticated date-time library. In Java that means either:
Joda-Time
java.time (built into Java 8, inspired by Joda-Time).
Time Zone
The time zone is crucial in determining the day and day-of-week. Use proper time zone names, never the 3 or 4 letter codes.
If you ignore time zone, the JVM’s current default time zone will be applied implicitly. This means different outputs when moving your app from one machine to another, or when a sys admin changes the time zone of host machine, or when any Java code in any thread of any app within the same JVM decides to call setDefault even during your app‘s execution.
Example Code To Get Next Day-Of-Week
Here is example code using Joda-Time 2.7.
Get the time zone you desire/expect. If working in UTC, use the constant DateTimeZone.UTC.
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
Get the date-time value you need. Here I am using the current moment.
DateTime dateTime = DateTime.now( zone );
Specify the future day-of-week you want. Note that Joda-Time uses the sensible # 1 for first day of week, rather than zero-based counting found in java.util.Calendar. First day of week is Monday, per international norms and standards (not Sunday as is common in United States).
int dayOfWeek = DateTimeConstants.SATURDAY;
The withDayOfWeek command may go back in time. So we use a ternary operator (?:) to make sure we go forwards in time by adding a week as needed.
DateTime future = ( dateTime.getDayOfWeek() < dayOfWeek )
? dateTime.withDayOfWeek( dayOfWeek )
: dateTime.plusWeeks( 1 ).withDayOfWeek( dayOfWeek );
You may want to adjust the time-of-day to the first moment of the day to emphasize the focus on the day rather than a particular moment within the day.
future = future.withTimeAtStartOfDay(); // Adjust time-of-day to first moment of the day to stress the focus on the entire day rather than a specific moment within the day. Or use `LocalDate` class.
Dump to console.
System.out.println( "Next day # " + dayOfWeek + " after " + dateTime + " is " + future );
When run.
Next day # 6 after 2015-04-18T16:03:36.146-04:00 is 2015-04-25T00:00:00.000-04:00
How can I get UTC DateTime from the following code? Right now with these lines of code, I get an output like this Fri Dec 31 05:30:00 IST 9999. Is this output is correct? I mean to say is this time is the UTC time. Any suggestions or help?
Code snapshot
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.set(9999, 11, 31, 0, 0, 0);
Date date = cal.getTime();
System.out.println(date);
Well, the output is correct in that it's what I'd expect for midnight UTC when you're running on a system in IST. Date.toString() always uses your system local time zone - because it doesn't have any other information. A Calendar knows its time zone, but a Date doesn't. The underlying information is just "the number of milliseconds since the Unix epoch".
If you want to convert a Date to a textual representation in a particular time zone, use SimpleDateFormat and specify the time zone there.
The problem here is that you're using the Date.toString() method that returns the local time zone.
You can use this code to get the current time in UTC:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
And then just use that object to get the time you want and use it, do note that cal.getTimeInMillis() or getTime() both return the time from the Epoch that is set to January 1, 1970 00:00:00.000 GMT (Gregorian). So if you want to print the time or use it for something other then calculate the difference in time you can use, for example:
System.out.println(cal.get(Calendar.YEAR));
However if you want to get the difference of time between this time and another you should create another calendar instance for that other time (because of the way getTimeInMillis() work). So you can just do something like:
Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
time.set(Calendar.YEAR, year);
time.set(Calendar.MONTH, month);
time.set(Calendar.DAY_OF_MONTH, day_of_month);
time.set(Calendar.HOUR_OF_DAY, hour_of_day);
time.set(Calendar.MINUTE, minute);
time.set(Calendar.SECOND, second);
long difInMillis = cal.getTimeInMillis() - time.getTimeInMillis();
Also you should always remember that the month starts from 0 and not from 1, to be sure you can use Calendar.[your_month_here] and check the values.
You can find more information here: http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html
In my Android Application, I am trying to convert Date/Time to Milliseconds, check the below code:
public long Date_to_MilliSeconds(int day, int month, int year, int hour, int minute)
{
Calendar c = Calendar.getInstance();
c.setTimeZone(TimeZone.getTimeZone("UTC"));
c.set(year, month, day, hour, minute, 00);
return c.getTimeInMillis();
}
Problem: I am getting 1290455340800(Nov 22 14:49:00 EST 2010) for Nov 22 19:49:00 EST 2010 (i.e. 5 hours back)
FYI, I am Currently in Indian TimeZone, but application can be executed from any country. so How do i exact Convert the date/time into the Milliseconds?
This line
c.setTimeZone(TimeZone.getTimeZone("UTC"));
Is probably causing the issue. There is no need to set the TimeZone as the current default is used.
My guess is that you're calling Date_to_MilliSeconds(22, 10, 2010, 19, 49). Your code explicitly uses UTC, so it's going to treat whatever you pass it in as UTC.
Just like your previous question (which makes me tempted to close this as a duplicate) it's unclear what you're really trying to do.
If you want to provide a local time to your method, you need to specify a local time zone. If you need to use a local time in the user's time zone, try setting the time zone to TimeZone.getDefault() - although I'd expect that to be the default anyway. If you want to provide a UTC time to your method, you need to specify a UTC time zone (as you are here).
What are you really trying to do?
In this piece of code, you are getting the amount of milliseconds since 01/01/1970 00:00 in your timezone for Nov 22 19:49:00 EST 2010 in UTC timezone. Why are you setting timezone to UTC?
The 5 hours difference is the difference between UTC and EST. You can use DateFormat.parse() to parse the input date if it's a string. Or you can use the code above and pass the desired timezone in c.setTimeZone() -- put in EST instead of UTC.
I'm using this:
public String timeToString(long time, String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault());
sdf.setTimeZone(TimeZone.getDefault());
return sdf.format(time + TimeZone.getDefault().getRawOffset()
+ TimeZone.getDefault().getDSTSavings());
}
I think it solves the TimeZone problems.