I wanna see if someDate has any day in it. Am I checking it right?
Calendar cal = Calendar.getInstance();
cal.setTime(someDate); // someDate is a Date
int day = cal.get(Calendar.DAY_OF_MONTH);
if(day == 0){
// code //
}
I'm not sure what you mean by "has any day in it" - all Dates will have a day in them... :-)
Other than that, you probably want the following:
Calendar cal = Calendar.getInstance();
cal.setTime(someDate); // someDate is a Date
int day = cal.get(Calendar.DAY_OF_WEEK);
if(day == Calendar.SUNDAY){
// code //
}
The big change is that you want to get the DAY_OF_WEEK field; what your example does is gets the day within the month (e.g. September 15th would return "15"). Secondly, comparing with Calendar.SUNDAY (or equivalent) is clearer and less error-prone that directly comparing with e.g. 0, even if the code is equivalent.
Every date object will have a day. The day of the month is never going to be 0 though, it will be in the range 1-31. Meaning that your check will always fail.
If I understand correctly you want Calendar.DAY_OF_WEEK.
The answer by Andrzej Doyle is correct.
Just for the heck of it, here is that same kind of code but using the Joda-Time 2.3 library and Java 7.
Unlike java.util.Calendar, Joda-Time sensibly uses 1-based counting. So the days of the week are numbered 1 to 7. Furthermore, Joda-Time uses the standard (ISO 8601) approach where Monday is the first day of the week (1).
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
// Specify time zone rather than rely on default.
// Time Zone list… http://joda-time.sourceforge.net/timezones.html (not quite up-to-date, read page for details)
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime now = new DateTime( timeZone );
if( now.dayOfWeek().get() == DateTimeConstants.MONDAY ) {
System.out.println( "Today is a Monday." );
} else {
System.out.println( "Nope, today is some other day of week." );
}
Related
Let's say I have the current day, the next day, and the previous day. And I want to write a method that finds the first business day of the month by doing logical operations on them. For example, the first working day of November 2021 starts on the 4th, because the 3rd of the month has no working days due to holidays. In short, we need to write a program that takes into account non-working days and finds the first working day of each month.
Well, there is no standard Java library to get the dates of the holidays. That would be too localized, because holidays heavily depend on your country and region (except for widely known holidays, such as Christmas or Easter).
You must rely on some external source, for instance a holiday API. Once you have the holidays, you could easily get the first business day of a month.
In the code below, I've hardcoded the holidays as a Set of LocalDates. I also assumed that business days are from Monday to Friday.
public static Optional<LocalDate> firstBusinessDayOfMonth(YearMonth month) {
// I've hardcoded the holidays as LocalDates
// and put them in a Set
final Set<LocalDate> holidays = Set.of(
LocalDate.of(2021, 11, 1),
LocalDate.of(2021, 11, 2),
LocalDate.of(2021, 11, 3)
);
// For the sake of efficiency, I also put the business days into a Set.
// In general, a Set has a better lookup speed than a List.
final Set<DayOfWeek> businessDays = EnumSet.of(
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
);
return
// All dates of the month
month.atDay(1).datesUntil(month.plusMonths(1).atDay(1))
// Retain all business days. Use static imports from
// java.time.DayOfWeek.*
.filter(date -> businessDays.contains(date.getDayOfWeek()))
// Retain only dates not present in our holidays list
.filter(date -> !holidays.contains(date))
// Get the first
.findFirst();
}
To get the first business day of the current month, use firstBusinessDayOfMonth(YearMonth.now()).
Note that this method returns an Optional, because it could theoretically be the case that there is no business day within the whole month.
Thanks for all the answers and help, but this is what I wanted.
Here, in my isOperateDay variable, they say that the data they have already sent me from the other server is 1 business day, not 0 business day. What I just wanted to do was to check if the values between yesterday and today are the first working day.
As you can see, I'm taking yesterday's month and comparing it to today's month, if yesterday's month is different, it means it was the previous month and my current day's month is counted as the first working day.
#Data
class ST_XF_DWH {
private LocalDateTime previousDate;
private LocalDateTime currentDate;
private int isOperateDate;
}
public void isFirstWorkDay(ST_XF_DWH st_xf_dwh) {
LocalDateTime previousDate = st_xf_dwh.getPreviousDate();
LocalDateTime currentDate = st_xf_dwh.getCurrentDate();
if (previousDate.getMonth() != currentDate.getMonth() && st_xf_dwh.getIsOperateDate() == 1) {
System.out.println("Is First Work Day" + st_xf_dwh.getCurrentDate());
} else {
System.out.println(st_xf_dwh.getCurrentDate() + "is not First Work Day");
}
}
I am trying to build a simple program with java.util.Calendar. When trying to get the weekday before, my output always stays the same. Code and what I tried below:
Calendar c = Calendar.getInstance();
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, day);
c.set(Calendar.YEAR, year);
int date = c.get(Calendar.DAY_OF_WEEK);
return new SimpleDateFormat("EEEE").format(date).toUpperCase();
This was my code at the start. I have tried subtracting day by one:
day = day-1;
I have tried adding minus one to both the Day of Month and Day of week field:
c.add(Calendar.DAY_OF_WEEK, -1);
c.add(Calendar.DAY_OF_MONTH, -1);
I think that it has something to do with my SimpleDateFormat, but I am not sure.
I am trying to build a simple program with java.util.Calendar.
That is impossible. Specifically, the 'simple program' part. Nothing that uses Calendar is simple.
The calendar API is horrible; it makes no sense (the first month of the year is... 0, to change values, you have to use int constants, which isn't idiomatic java), and is confused about what it is trying to represent (it's not a calendar, it's a date/time value, or, is it? Is it solarflares time, appointment time, or alarmclock time? It's confused and doesn't know). That's why there is a new API: java.time. Java does not remove stuff even if it is obsolete, because that would break old code. So, the fact that Calendar is still around doesn't mean much.
Use java.time.
I think that it has something to do with my SimpleDateFormat, but I am not sure.
It doesn't. But let's forget about this silly API and use java time instead!
// note that in calendar, january is 0, and that is insane.
// in localdate, it is 1, which is sane.
// thus, assuming you have `month = month - 1;` someplace in your code...
// remove that.
LocalDate date = LocalDate.of(year, month, day);
DayOfWeek day = date.getDayOfWeek();
System.out.println(day);
Wanna go back a day? Okay.
DayOfWeek day = date.minusDays(1).getDayOfWeek();
System.out.println(day);
The reason this fails is that you aren't invoking the method you think you are. There is no SimpleDateFormat#format(int). But SimpleDateFormat extends Format, which declares Format#format(Object). Your int is boxed to Integer and then the relevant code in Format#format(Object) is
if (obj instanceof Date)
return format( (Date)obj, toAppendTo, fieldPosition );
else if (obj instanceof Number)
return format( new Date(((Number)obj).longValue()),
toAppendTo, fieldPosition );
else
throw new IllegalArgumentException("Cannot format given Object as a Date");
At this point, since the value you passed is boxed to Integer which extends Number, the second branch of the if-else is taken and your day-of-week value is converted to a date via the constructor. The number is interpreted as a millisecond value and when you subtracted 1 you changed the time by 1 millisecond, not 1 day.
All that said, you should NOT be using Calendar, use the new date/time API in the java.time package.
Hi buddies I'm in a trouble trying to migrate a behavior from calendar to localdate.
payDate.set(Calendar.DAY_OF_MONTH,payDay)
Lets imagine that payDate had the current date, 2020-01-29
for business reasons payDay can had the value of 0, so, when the previous code line is executed with the previous scenario, the result is that payDate update the date to 2019-12-31,
that is to say the the date back to the last day of the past month.
I'm not sure, the technical reason of this, if someone can explain to me this I'll be so thankful, I tried checking the java doc but it was not helpful.
So I need to replicate that behavior with LocalDate java library. From my point of view; the similar of set method from Calendar with the value of DAY_OF_MONTH in LocalDate is:
payDate.withDayOfMonth(payDay)
But when the below scenario is presented and payDay is equal to 0 I get an error:
java.time.DateTimeException: Invalid value for DayOfMonth (valid values 1 - 28/31): 0
Also I had some ideas about how can I get the same result of calendar in localDate when the rule comes on (if payDay is 0, return to the last day of previous month), but are too verbose.
If you know a similar behavior on LocalDate please help me. Thanks.
TL;DR: Use payDate = payDate.plusDays(payDay - payDate.getDayOfMonth());
The behavior of Calendar you're describing is documented in the javadoc:
Leniency
Calendar has two modes for interpreting the calendar fields, lenient and non-lenient. When a Calendar is in lenient mode, it accepts a wider range of calendar field values than it produces. When a Calendar recomputes calendar field values for return by get(), all of the calendar fields are normalized. For example, a lenient GregorianCalendar interprets MONTH == JANUARY, DAY_OF_MONTH == 32 as February 1.
When a Calendar is in non-lenient mode, it throws an exception if there is any inconsistency in its calendar fields. For example, a GregorianCalendar always produces DAY_OF_MONTH values between 1 and the length of the month. A non-lenient GregorianCalendar throws an exception upon calculating its time or calendar field values if any out-of-range field value has been set.
To show the effect of this, try setting the date of a Calendar to January 70, 2020:
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(2020, Calendar.JANUARY, 70);
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()));
Output
2020-03-10
You would get the same result if you did:
cal.set(2020, Calendar.JANUARY, 1);
cal.add(Calendar.DAY_OF_MONTH, 69);
LocalDate is always non-lenient, so you can't set the day-of-month value to a value that is out-of-range. You can however get the same result as what Calendar does, by changing the operation to "add" instead of "set".
So, if you have a particular date, e.g. the 2020-01-29 date mentioned in the question, and you want to "set" the day-of-month value to 70 or 0, with same lenient overflow logic as Calendar has, do this:
LocalDate date = LocalDate.parse("2020-01-29");
date = date.plusDays(70 - date.getDayOfMonth());
System.out.println(date);
LocalDate date = LocalDate.parse("2020-01-29");
date = date.plusDays(0 - date.getDayOfMonth());
System.out.println(date);
Output
2020-03-10
2019-12-31
As you can see, date.plusDays(dayToSet - date.getDayOfMonth()) will give you the desired result.
Here’s how I would go about it:
LocalDate payDate = LocalDate.now(); // or whatever
int payDay = 0;
if (payDay == 0) {
// simulate `GregorianCalendar` behaviour: day 0 is the day before day 1
payDate = payDate.withDayOfMonth(1).minusDays(1);
} else {
payDate = payDate.withDayOfMonth(payDay);
}
System.out.println(payDate);
When I ran the snippet just now, the output was the date you already mentioned:
2019-12-31
If we wanted it shorter, we could use payDate.withDayOfMonth(1).minusDays(1).plusDays(payDay) or the trick from Andreas’ answer, and we would not need the if statement. I would not, though. (1) It’s harder to read. (2) It doesn’t give the validation of payDay that comes for free in the snippet above.
The confusing behaviour of Calendar comes from not range checking the argument to set(). So day 0 of the month is the day before day 1 of the month. Day -1 would be the day before that, and so forth. It’s in this snippet from the documentation (or was supposed to be, at least):
When a Calendar is in lenient mode, it accepts a wider range of
calendar field values than it produces. When a Calendar recomputes
calendar field values for return by get(), all of the calendar
fields are normalized. For example, a lenient GregorianCalendar
interprets MONTH == JANUARY, DAY_OF_MONTH == 32 as February 1.
You may read it with this snippet from the documentation of the setLenient method:
The default is lenient.
Links
Documentation of Calendar
Documentation of Calendar.setLenient()
You're not going to be able to just invoke one method to achieve the same results. If you're sure that setting DAY_OF_MONTH to 0 should cause it to roll back one month (this is the type of thing I'd run past a business analyst or product owner for a sanity check) then you're going to have to do something like this:
int payDay = 0;
LocalDate payDate = LocalDate.of(2020, Month.JANUARY, 29);
if(payDay == 0) {
payDate = payDate.minusMonths(1);
payDay = payDate.lengthOfMonth();
}
payDate = payDate.withDayOfMonth(payDay);
Another approach:
int payDay = 0;
LocalDate payDate = LocalDate.of(2020, Month.JANUARY, 29);
if(payDay == 0) {
payDate = payDate.withDayOfMonth(1).minusDays(1);
} else {
payDate = payDate.withDayOfMonth(payDay);
}
First I get:
LocalDate today = LocalDate.now();
and second
Date date = new Date();
date.setDate(Integer.valueOf(s[0]));
date.setMonth(Integer.valueOf(s[1]));
date.setYear(Integer.valueOf(s[2]));
LocalDate topicDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
How to check whether the differences between the first date and the second is 7 days?
For example, today is 03-08-2015 and the second date is 20-07-2015 and the difference between is more than 7 days, but how to check this?
Should I convert date to millisecond?
I Believe that is still the best way at the moment.
You can view some insights on the subject here:
Calculate date/time difference in java
You could convert to milliseconds or you could individually check if the year was larger, then if they are the same check to see if the month is larger then check day. Converting to milliseconds would be very easy though.
I believe you are looking for something like this:
Date date = /*your date object you want to compare*/;
Instant now = Instant.now();
Instant sevenDaysFromYourDate = Instant.ofEpochMilli(date.getTime()).plus(Duration.ofDays(7));
if (now.isAfter(sevenDaysFromYourDate)) {
//today is more than seven days past date
}
LocalDate today = LocalDate.now();
if (topicDate.isAfter(today.plusDays(7))) {
System.out.println("Yes");
}
else {
System.out.println("No");
}
Since you are using Java 8 LocalDate, you can use the plusDays or minusDays methods of the LocalDate class.
Furthermore, you shouldn't be using an (old, not recommended for use) java.util.Date object to create your second date. It's better to use LocalDate.of which builds a date from the year, month and day.
Example code:
LocalDate today = LocalDate.now();
LocalDate topicDate = LocalDate.of(
Integer.valueOf(s[2]),
Integer.valueOf(s[1]),
Integer.valueOf(s[0]));
System.out.println(today);
System.out.println(topicDate);
if ( today.minusDays(7).equals(topicDate)) {
System.out.println( "Exactly a week difference between today and topicDate");
} else if ( today.minusDays(7).compareTo(topicDate) > 0 ) {
System.out.println("TopicDate is more than a week before today");
} else {
System.out.println("TopicDate is less than a week before today");
}
Note that you can use the compareTo for exact equality as well - I just wanted to demonstrate that for equality, equals also works.
And of course, there are the isAfter and isBefore methods that also do the comparison in an elegant way.
In Java, how would I go about constructing a utility that would take a range of dates (start and end date) and then would see how many times a given partial date ( the month and day-of-month) appears in that range, and will add an entry to a list for each match.
In my instance, I want to give it a range of say 5 years - starting Jan 1st 2014 and going to Dec 31st 2019. My check date is the 2nd August. I want the method to return the full information about each match of any August 2 of any year in the range. So for 2014 is will return Saturday 2nd August 2014, then Sunday 2nd August 2015 etc and so on.
I've been trying to get something working so far with Joda Time and the default date/calendar classes in Java and I'm just getting myself in a mess.
Thanks,
S
Edit: How silly of me, apologies for not adding my code :(
public static List<Date> getDaysInRange(Date startdate,
Date enddate,
Date checkDate) {
SimpleDateFormat sdf = new SimpleDateFormat("MMdd");
List<Date> dates = new ArrayList<>();
Calendar cal = new GregorianCalendar();
cal.setTime(startdate);
while (cal.getTime().before(enddate)) {
if (sdf.format(cal.getTime()).equals(sdf.format(checkDate))) {
Date result = cal.getTime();
dates.add(result);
}
cal.add(Calendar.DATE, 1);
}
return dates;
}
Date-Only
Since you want only a date without time-of-day and without time zone, use a date-only class. The old java.util.Date/.Calendar classes lack such a class. And those old classes are notoriously troublesome and flawed.
Instead use either:
Joda-Time
java.time, built into Java 8, inspired by Joda-Time.
Joda-Time
Here is some untested code using Joda-Time 2.6.
The main idea is to focus on the small set of possible year numbers rather than test every day of year. In the example below, that means six date-time values to compare rather than thousands. Besides efficiency, the purpose of the code becomes more apparent.
The arguments to your routine should be a month number and a day-of-month number, a pair of ints or Integers, rather than a Date. As seen in this examples two int variables, month and day.
LocalDate start = new LocalDate( 2011, 2, 3 );
LocalDate stop = new LocalDate( 2016, 4, 5 );
int yearStart = start.getYear();
int yearStop = stop.getYear();
int month = 11;
int day = 22;
for ( i = yearStart, i <= yearStop, i++ )
{
LocalDate x = new LocalDate( i, month, day );
boolean matchStart = ( x.isEqual( start ) || x.isAfter( start ) );
boolean matchStop = x.isBefore( stop ); // Half-Open approach where beginning of range is inclusive while ending is exclusive.
if ( matchStart && matchStop )
{
// Add to collection of LocalDate objects.
// Later you can ask each LocalDate object for its day-of-week.
{
}
java.time
The java.time package also offers a LocalDate class. The code would be similar to the above Joda-Time example.
I think using SimpleDateFormat is a bad idea. Use Calendar for comparison directly, like this
cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH) && cal1.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH)