I am trying to determine what day of the week is the first day of the month but for some reason it is not returning me the correct day of the week.
Here is my code below:
CalendarMonth[] months = CalendarUtils.constructMonthViewArray(new GregorianCalendar());
public static CalendarMonth[] constructMonthViewArray(Calendar cal) {
CalendarMonth[] months = new CalendarMonth[CALENDAR_GRID_SIZE];
int year = cal.get(cal.YEAR);
int month = cal.get(cal.MONTH);;
// calculate how many days in the month
int numOfDays = getNumOfDaysInMonth(cal);
// calculate what day(mon-sunday) is the 1st of the month
int firstDayOfMonth = getFirstDayOfMonth(cal);
private static int getFirstDayOfMonth(Calendar cal) {
int firstDay = cal.get(Calendar.DAY_OF_WEEK);
Log.d(TAG, "");
// decrement it because our array deals with values 0-6(indexes)
firstDay--;
if (firstDay == 0) {
firstDay = 6;
} else {
// decrement again so that the days start from 0.
firstDay--;
}
return firstDay;
}
The line from "int firstDay = cal.get(Calendar.DAY_OF_WEEK);" fails to give me the correct day of the week and returns the value 2 for getting the 1st day of this month(January 2011) when the first of the month was on a Saturday(7).
Am I missing something? I have debugged and checked what month, year and date the cal variable is set and it indeed indicated today's date as corrected but when i get the day of week it doesn't get the value 7.
I can't reproduce the problem you're seeing. As Michael says, there's a lot of code you haven't shown us, but Calendar.getDayOfWeek definitely works:
import java.util.*;
public class Test {
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar();
calendar.set(2011, 0, 1); // 0 = January
System.out.println(calendar.get(Calendar.DAY_OF_WEEK)); // Prints 7
}
}
Did you maybe forget that months are 0-based in java.util.Calendar?
If you can produce a similar short but complete program which shows the wrong day of the week, please post it.
The fact that you're decrementing firstDay twice within getFirstDayOfMonth seems somewhat odd, as well as the fact that it doesn't really reflect the name of the method (as Michael mentioned).
Finally, my constant recommendation for Java date/time handling: if you can possibly use Joda Time instead of java.util.Calendar, do so. It's a much, much better API.
The code of getFirstDayOfMonth() appears not to do what the method name says at all - but to actually understand what is happening, we need to see all the code that is involved, especially how the calendar initialized and the code of getNumOfDaysInMonth()
One thing to keep in mind: what is considered the first day of the week depends on the locale, as per getFirstDayOfWeek()
tl;dr
Convert from terrible legacy classes (Calendar, GregorianCalendar, etc.) to modern java.time classes (ZonedDateTime, LocalDate, etc.). Then get object for day-of-week, and ask it to automatically localize the name of that day of the week.
(GregorianCalendar) myJavaUtilCalendar // Cast your `Calendar` to `GregorianCalendar` assuming it actually is one.
.toZonedDateTime() // Convert from legacy class to modern class.
.toLocalDate() // Extract date-only object, without time-of-day and without time zone.
.with( // Adjust to another date by calling `TemporalAdjuster` implementation such as are found in `TemporalAdjusters` class.
TemporalAdjusters.firstDayOfMonth() // Adjust to the first day of the month.
) // Returns another `LocalDate` object, for the first of the month.
.getDayOfWeek() // Obtain a `DayOfWeek` enum object, one of seven pre-defined objects representing each day of the week.
.getDisplayName( // Automatically localize.
TextStyle.FULL , // Specify how long or abbreviated.
Locale.CANADA_FRENCH // Or `Locale.US` etc. to specify the human language and cultural norms to use in localizing.
) // Returns text in a `String` such as “Monday” or “lundi”.
java.time
The java.util.Calendar/.Date and related classes are a confusing mess as you have learned the hard way.
The modern approach uses java.time classes.
Conversion
If starting with a java.util.Calendar object, convert to java.time.
An Instant is a moment on the timeline in UTC.
Instant instant = myJavaUtilCalendarObject.toInstant();
Apply a time zone in order to get a date in order to get a day-of-week.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );
Note that a time zone is critical in determining a date (and therefore day-of-week). "Today" is not the same date everywhere in the world simultaneously. A new day dawns earlier, for example, in Paris than in Montréal.
First Day Of Month
Let's move to the first of the month by calling withDayOfMonth.
ZonedDateTime zdtFirstOfMonth = zdt.withDayOfMonth(1);
Note that moving a date-time to first of month has issues. Anomalies such as Daylight Saving Time (DST) could have a surprising effect. Read the doc so you understand the behavior.
DayOfWeek
For day of week, use the well-named DayOfWeek enum.
DayOfWeek dayOfWeek = zdtFirstOfMonth.getDayOfWeek();
I suggest passing instances of this enum rather than a magic number like 2, 7, etc. But if you insist, you can extract an integer.
int dayOfWeekNumber = dayOfWeek.getValue();
To get a String of the name of day-of-week, let java.time generate a localized String via the getDisplayName method.
String output = dayOfWeek.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH ); // Or Locale.ENGLISH
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Related
I have the following timestamp stored in a long variable: 1471906800000 this stores the date 18/01/2017 00:00:00
I'm trying to create another timestamp that will contain the same date as stored in the first timestamp, but with the time being 23:59:59 -
I don't even know where to start
How could I achieve this in the most simple way possible in Java?
Thanks.
Using Calendar will help you:
long l = 1471906800000l;
Date date = new Date(l);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
l = calendar.calendar.getTimeInMillis();
Both of the other Answers use outmoded classes, now supplanted by the java.time classes.
Perhaps your input number is a count of milliseconds from the epoch of first moment of 1970 in UTC (1970-01-01T00:00:00Z). But I do not get the result you stated in the question.
long input = 1_471_906_800_000L ;
Instant instant = Instant.ofEpochMilli( input );
input: 1471906800000
instant: 2016-08-22T23:00:00Z
But you expected the value of 18/01/2017 00:00:00, off by a few months. If your input is not a count of milliseconds from 1970-01-01T00:00:00Z, you need to edit your Question to specify.
If you made a mistake in your expected output, then let's proceed to set the time-of-day.
If you wanted the second before the end of the day, I suggest subtracting a second from the start of the following day rather than hard-coding the time of 23:59:59. That time-of-day may be invalid because of anomalies such as Daylight Saving Time (DST). Also, unless you meant intend to work in UTC, you need to move into the desired/expected time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
Extract a LocalDate, for a date-only value without time-of-day and without time zone.
LocalDate ld = zdt.toLocalDate();
Move to next day.
LocalDate ldNextDay = ld.plusDays( 1 );
Ask for first moment.
ZonedDateTime zdtNextDay = ldNextDay.atStartOfDay( z );
Subtract a second to move back into previous day.
ZonedDateTime zdtPreviousDay = zdtNextDay.minusSeconds( 1L );
However, I suspect you are taking the wrong approach to handling date-time values. Rather than trying to determine the end of a day, I strongly suggest you follow the common practice of using the Half-Open approach to spans of time. In Half-Open, the beginning is inclusive while the ending is exclusive.
So a full day starts with the first moment of one day and runs up to, but not including, the first moment of the next day. This way you avoid the problem of the last second or trying to get the infinitely divisible fraction of a second.
ZonedDateTime zdtDayStart = LocalDate.of( 2017 , Month.JANUARY , 18 ).atStartOfDay( 1 );
ZonedDateTime zdtDayStop = zdtDayStart.plusDays( 1 );
You may find the Interval class in the ThreeTen-Extra project helpful.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I'm assuming that you don't specifically want the time at 23:59:59, but rather a time 1 minute before the start of the next day.
You should use a date/time library. I know jodatime better, so this example is written using that, but you may be able to use the Java 8 time API instead.
DateTime today = new DateTime(1471906800000L, TIME_ZONE);
// You may want to check that today is actually at the start of the day.
// e.g. today.equals(today.withTimeAtStartOfDay());
DateTime lastMinuteOfToday =
today.toLocalDate()
.plusDays(1)
.toDateTimeAtStartOfDay(TIME_ZONE)
.minusMinutes(1);
long lastMinuteOfTodayMillis = lastMinuteOfToday.getMillis();
Knowing the timezone is important to do this correctly.
This question already has answers here:
Why is January month 0 in Java Calendar?
(18 answers)
Closed 2 years ago.
Calendar rightNow = Calendar.getInstance();
String month = String.valueOf(rightNow.get(Calendar.MONTH));
After the execution of the above snippet, month gets a value of 10 instead of 11. How come?
Months are indexed from 0 not 1 so 10 is November and 11 will be December.
They start from 0 - check the docs
As is clear by the many answers: the month starts with 0.
Here's a tip: you should be using SimpleDateFormat to get the String-representation of the month:
Calendar rightNow = Calendar.getInstance();
java.text.SimpleDateFormat df1 = new java.text.SimpleDateFormat("MM");
java.text.SimpleDateFormat df2 = new java.text.SimpleDateFormat("MMM");
java.text.SimpleDateFormat df3 = new java.text.SimpleDateFormat("MMMM");
System.out.println(df1.format(rightNow.getTime()));
System.out.println(df2.format(rightNow.getTime()));
System.out.println(df3.format(rightNow.getTime()));
Output:
11
Nov
November
Note: the output may vary, it is Locale-specific.
As several people have pointed out, months returned by the Calendar and Date classes in Java are indexed from 0 instead of 1. So 0 is January, and the current month, November, is 10.
You might wonder why this is the case. The origins lie with the POSIX standard functions ctime, gmtime and localtime, which accept or return a time_t structure with the following fields (from man 3 ctime):
int tm_mday; /* day of month (1 - 31) */
int tm_mon; /* month of year (0 - 11) */
int tm_year; /* year - 1900 */
This API was copied pretty much exactly into the Java Date class in Java 1.0, and from there mostly intact into the Calendar class in Java 1.1. Sun fixed the most glaring problem when they introduced Calendar – the fact that the year 2001 in the Gregorian calendar was represented by the value 101 in their Date class. But I'm not sure why they didn't change the day and month values to at least both be consistent in their indexing, either from zero or one. This inconsistency and related confusion still exists in Java (and C) to this day.
Months start from zero, like indexes for lists.
Therefore Jan = 0, Feb = 1, etc.
From the API:
The first month of the year is JANUARY
which is 0; the last depends on the
number of months in a year.
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Calendar.html
tl;dr
LocalDate.now() // Returns a date-only `LocalDate` object for the current month of the JVM’s current default time zone.
.getMonthValue() // Returns 1-12 for January-December.
Details
Other answers are correct but outdated.
The troublesome old date-time classes had many poor design choices and flaws. One was the zero-based counting of month numbers 0-11 rather than the obvious 1-12.
java.time
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.
Now in maintenance mode, the Joda-Time project also advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.
Months 1-12
In java.time the month number is indeed the expected 1-12 for January-December.
The LocalDate class represents a date-only value without time-of-day and without time zone.
Time zone
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
int month = today.getMonthValue(); // Returns 1-12 as values.
If you want a date-time for a time zone, use ZonedDateTime object in the same way.
ZonedDateTime now = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
int month = now.getMonthValue(); // Returns 1-12 as values.
Convert legacy classes
If you have a GregorianCalendar object in hand, convert to ZonedDateTime using new toZonedDateTime method added to the old class. For more conversion info, see Convert java.util.Date to what “java.time” type?
ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime();
int month = zdt.getMonthValue(); // Returns 1-12 as values.
Month enum
The java.time classes include the handy Month enum, by the way. Use instances of this class in your code rather than mere integers to make your code more self-documenting, provide type-safety, and ensure valid values.
Month month = today.getMonth(); // Returns an instant of `Month` rather than integer.
The Month enum offers useful methods such as generating a String with the localized name of the month.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
cal.get(Calendar.MONTH) + 1;
The above statement gives the exact number of the month. As get(Calendar.Month) returns month starting from 0, adding 1 to the result would give the correct output. And keep in mind to subtract 1 when setting the month.
cal.set(Calendar.MONTH, (8 - 1));
Or use the constant variables provided.
cal.set(Calendar.MONTH, Calendar.AUGUST);
It would be better to use
Calendar.JANUARY
which is zero ...
I have an object with some dates and I'd like to return them in the getter. The problem is that i need to do Date.toString(); because I have to print them, and when the date is null I get a NullPointerException.
I was thinking about returning the date 0/0/0 when the date is null, but I don't know how to set this value. Is there any way? Just like new Date(0) returns the 1970-01-01-00:00:00, is there anything similar to this but to return 0/0/0?
Thanks!
There is no Date 0/0/0, by definition, as there is no Day 0 and no Month 0. A day is a member of the set {1,..,28 or 30 or 31} and month is a member of the set {1,...12}. Hence, it is impossible - and it is good that it is impossible - to express 0/0/0 as Date Object.
The terrible Date and Calendar classes were supplanted years ago by the java.time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety. Ditto for Year & YearMonth.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Zero-date senseless
is there anything similar to this but to return 0/0/0?
No.
Trying to represent a null with a date of all zeros is the wrong way to go. There is no such thing as a date of all zeros (year, month, and day all being zero).
Instead, pick an arbitrary date to use as a special value. Document thoroughly your choice and its meaning.
Do not choose a date too distant in time. Many libraries and databases are limited in their range of values. You do not want your data to break there.
Generally I would suggest using the epoch of 1970-01-01T00:00:00Z, the first moment of 1970 in UTC (the Z means UTC, and is pronounced “Zulu”). This moment is used as the epoch reference for Unix, the legacy date-time classes bundled with Java, and the modern date-time classes built into Java 8 and later. So many programmers and sysadmins will recognize this moment as special. The java.time classes include a constant for your convenience: Instant.EPOCH.
Obviously my suggestion applies to common business-oriented apps interested in forward-looking near dates, with past history not reaching back to 1970. If that does not meet your needs, pick another arbitrary value, such as 1900-01-01.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Java uses the Gregorian Calendar which has no 0 year. Also, you have to keep in mind that there is now zero month either. Setting a month to '0' would result in getting January, as the months are based on 0-index. Zero day does not exist either.
Assuming that you are getting and returning "modern" dates (AD), you could set your "lower bound" date in BC era. So, when you get a null date you could return a BC date to differentiate it from your actual ones. Here's the code:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.ERA, GregorianCalendar.BC); //Set the BC era
cal.set(Calendar.YEAR, 1); //Set the year to 1 BC
cal.set(Calendar.MONTH, 0); //Set the month to January
cal.set(Calendar.DAY_OF_MONTH, 1); //Set the day to 1st
DateFormat df = new SimpleDateFormat("yyyy MMM d G"); //Format the date
String returnedDate = df.format(cal.getTime()); //Generate a String of it for other use
You could customize the code to your needs if you are also getting dates from BC era (maybe by setting an even older date).
EDIT: Of course you could use what the others have suggested, namely checking for null and returning a "0/0/0" String but this may cause further problems later on, when you will try to parse the aforementioned String. Also, due to the fact that by definition 0/0/0 is not a valid date in the Gregorian Calendar (see clarification), you should avoid using this "wildcard" String and set an actual date, as I detailed above.
CLARIFICATION: The Gregorian Calendar does not contain neither a 0 year nor a 0 month or 0 day by definition and not by implementation in Java (meaning it's not an intentional limitation, it's part of its concept).
Class: LocalDate
Package: Threetenabp
My solution was to create LocalDate constants using the EPOCH date as basis with LocalDate.ofEpochDay(). And instead of returning a null date (that does not exist) I return a LocalDate object according to the case evaluated. Then depending on what I get back the getBirthdate method in my domain I do something.
Definition of constants
public class LocalDateUtils {
public static final LocalDate EMPTY_FIELDS = createLocalDate(0);
public static final LocalDate EMPTY_FIELD_DAY_OF_MONTH = createLocalDate(1);
public static final LocalDate EMPTY_FIELD_MONTH = createLocalDate(2);
public static final LocalDate EMPTY_FIELD_YEAR = createLocalDate(3);
/**
* Purpose: Create a date with #param epochDay days added
* Observation: EPOCH (1970-01-01)
*/
private static LocalDate createLocalDate(long epochDay) {
return LocalDate.ofEpochDay(epochDay);
}
}
Implementation
/**
* Purpose: Describe a birthday or a constant indicating empty field (s).
* Observation: According to if the parameters are zeros.
*/
LocalDate getBirthdate(int year,
int month,
int dayOfMonth) {
if (dayOfMonth == 0 && month == 0 && year == 0)
return LocalDateUtils.EMPTY_FIELDS;
if (dayOfMonth == 0)
return LocalDateUtils.EMPTY_FIELD_DAY_OF_MONTH;
if (month == 0)
return LocalDateUtils.EMPTY_FIELD_MONTH;
if (year == 0)
return LocalDateUtils.EMPTY_FIELD_YEAR;
return LocalDate.of(year, month, dayOfMonth);
}
Usage
if (getBirthdate() == LocalDateUtils.EMPTY_FIELDS) {
}
if (getBirthdate() == LocalDateUtils.EMPTY_FIELD_DAY_OF_MONTH) {
}
if (getBirthdate() == LocalDateUtils.EMPTY_FIELD_MONTH) {
}
if (getBirthdate() == LocalDateUtils.EMPTY_FIELD_YEAR) {
}
Source
GL
This simple approach can get you what you need, as already mentioned in the comments to your question:
public String dateString(Date date) {
if (date != null)
return date.toString();
else
return "0/0/0";
}
or
String dateString;
try {
dateString = date.toString();
}
catch(NullPointerException e) {
dateString = "0/0/0";
}
Update: the second alternative is discouraged as suggested in the comments.
I need to get the dates for Monday and Friday last week. To do this, i am getting the date of Monday this week and subtracting 7 days. This gives me the date for Monday last week.
To get the date for Friday i have to add 4. This confused me a bit because for some reason the first day of the week is Sunday as opposed to Monday here in the UK.
Anyway, here is how i am getting the dates.
// Get the dates for last MON & FRI
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
cal.add(Calendar.DAY_OF_WEEK, -7);
cal.set(Calendar.HOUR_OF_DAY,0);
cal.set(Calendar.MINUTE,0);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MILLISECOND,0);
// Get the date on Friday
cal.add(Calendar.DAY_OF_WEEK, 4);
cal.set(Calendar.HOUR_OF_DAY,23);
cal.set(Calendar.MINUTE,59);
cal.set(Calendar.SECOND,59);
cal.set(Calendar.MILLISECOND,0);
The above works but i am interested if there is anything wrong with the logic. I.e. will it work for Februarys, leap years etc.
Feel free to suggest a better solution/approach.
Thanks
tl;dr
get the dates for Monday and Friday last week
LocalDate // Represent a date only, without a time-of-day, and without a time zone or offset.
.now // Capture the current date as seen through the wall-clock time used by the people of a certain region (a time zone).
(
ZoneId.of( "America/Montreal" )
) // Returns a `LocalDate` object.
.with // Move to another date.
(
TemporalAdjusters.previous( DayOfWeek.MONDAY ) // Returns an implementation of the `TemporalAdjuster` interface.
) // Returns another `LocalDate` object, separate and distinct from our original `LocalDate` object. Per the immutable objects design pattern.
Avoid legacy date-time classes
The other Answers use the troublesome old legacy date-time classes now supplanted by the java.time questions.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
ZoneId z = ZoneId.of( “America/Montreal” );
LocalDate today = LocalDate.now( z );
TemporalAdjuster
The TemporalAdjuster interface provides for adjustments to move from one date-time value to another. Find handy implementations in the TemporalAdjusters class (note the plural 's'). The previous adjuster finds any specified object from the DayOfWeek enum.
The Question does not exactly define “last week”. Last seven days? Standard Monday-Sunday period? Localized week, such as Sunday-Saturday in the United States? The week prior to today’s week or including today’s partial week?
I will assume the prior seven days were intended.
LocalDate previousMonday = today.with( TemporalAdjusters.previous( DayOfWeek.MONDAY ) ) ;
LocalDate previousFriday = today.with( TemporalAdjusters.previous( DayOfWeek.FRIDAY ) ) ;
By the way, if you want to consider the initial date if it happens to already be the desired day-of-week, use alternate TemporalAdjuster implementations: previousOrSame or nextOrSame.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Note: For Java 8 and above please take a look at Basil Bourque's answer (link).
Java 8 introduced a new time/date API which offers most of Joda-Time's functionality.
Joda-Time offers really nice methods for problems like that.
Getting the dates for Monday and Friday last week would look something like this using Joda Time:
DateTime today = DateTime.now();
DateTime sameDayLastWeek = today.minusWeeks(1);
DateTime mondayLastWeek = sameDayLastWeek.withDayOfWeek(DateTimeConstants.MONDAY);
DateTime fridayLastWeek = sameDayLastWeek.withDayOfWeek(DateTimeConstants.FRIDAY);
You can create DateTime objects from java.util.Date objects and vice versa so it is easy to use with Java dates.
Using the above code with the date
DateTime today = new DateTime("2012-09-30");
results in "2012-09-17" for Monday and "2012-09-21" for Friday, setting the date to
DateTime tomorrow = new DateTime("2012-10-01");
results in "2012-09-24" for Monday and "2012-09-28" for Friday.
You still have start of week set to sunday, which means that Calendar.MONDAY on a saturday is the monday before, while Calendar.MONDAY on a sunday is the next day.
What you need to do is (according to how you want it according to your comment above), to set the start of week to monday.
Calendar cal = Calendar.getInstance();
cal.setFirstDayOfWeek(Calendar.MONDAY);
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
cal.add(Calendar.DAY_OF_WEEK, -7);
...
Beyond that, and that the last second of friday isn't included in the range, your logic seems sound, and shouldn't have trouble with leap years/DST shifts etc.
The only thing I see wrong is that you are in fact testing the range Mo-Fr, and not, as stated, retrieving two specific days. It would be safer to test range Mo-Sa with exclusive upper bound.
You can use TemporalAdjusters to adjust the desired dates/days you are looking for.
Example:
LocalDate today = LocalDate.now();
LocalDate lastMonday = today.with(TemporalAdjusters.previous(DayOfWeek.MONDAY));
LocalDate lastFriday = today.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
At the moment, I'm creating a java schedule app and I was wondering how to find the current day of the week while using the Calendar class to get the first day of the week.
Here is the method I'm using in a class in order to set up a week schedule
public static String getSunday() {
SimpleDateFormat d = new SimpleDateFormat(dayDate);
Calendar specific = cal;
specific.add(Calendar.DAY_OF_YEAR, (cal.getFirstDayOfWeek() - ??));
return d.format(specific.getTime());
}
You can get the current day of the week by calling get() with Calendar.DAY_OF_WEEK
public int getTodaysDayOfWeek() {
final Calendar c = Calendar.getInstance();
return c.get(Calendar.DAY_OF_WEEK);
}
Also, while I'm not sure I understand exactly what you're trying to do, it looks fishy to me. (What's cal for example?)
tl;dr
how to find the current day of the week
DayOfWeek.from( LocalDate.now() )
set up a week schedule
LocalDate sunday =
LocalDate.now()
.with( TemporalAdjusters.nextOrSame( DayOfWeek.SUNDAY ) ) ;
LocalDate monday = sunday.plusDays( 1 ) ;
LocalDate tuesday = monday.plusDays( 1 ) ;
…
Details
The Question and other Answer both use outmoded classes.
The old date-time classes are poorly designed, confusing, and troublesome. Avoid them.
java.time
In Java 8 and later, we use the built-in java.time framework. Much of the functionality is back-ported to Java 6 & 7 (ThreeTen-Backport), and further adapted to Android (ThreeTenABP).
An Instant represents the current moment in UTC with a resolution up to nanoseconds.
Instant instant = Instant.now();
To get the day-of-week we must determine the date. Time zone is crucial in determining the date as the date can vary around the globe for any given moment. For example, a few minutes after midnight in Paris is a new day, while in Montréal it is still “yesterday”.
Use ZoneId to represent a time zone. Ask for a proper time zone name in format of continent/region. Never use the 3-4 letter abbreviations commonly seen in mainstream media as they are not true time zones, not standardized, and are not even unique(!).
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Use the handy DayOfWeek enum to determine the day of the week.
DayOfWeek dow = DayOfWeek.from( zdt );
You may interrogate the DayOfWeek object.
You may ask for a number from 1 to 7 where 1 is Monday and 7 is Sunday per the ISO 8601 standard. But do not pass this number around your code; instead pass around DayOfWeek objects to enjoy the benefits of type-safety and guaranteed valid values.
int dowNumber = dow.getValue();
You may want text, the name of the day of the week. Let java.time automatically translate the name into a human language. A Locale species which human language, and also specifies the cultural norms to use such as how to abbreviate and capitalize. The TextStyle enum indicates how long a name you want.
Locale locale = Locale.CANADA_FRENCH;
String output = dow.getDisplayName( TextStyle.FULL , locale );
To get the start of the week, ask for the previous Monday (or Sunday, whatever), or stick with today if it is a Monday. Use a TemporalAdjuster implementation found in TemporalAdjusters class.
LocalDate startOfWeek = zdt.toLocalDate().with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) );
If you need a date-time rather than date-only, ask java.time to get the first moment of the day (not always the time 00:00:00).
ZonedDateTime zdtWeekStart = startOfWeek.atStartOfDay( zoneId );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.