Related
I have a beginning date, let us say it is 2020-12-30 08:00:00, and I have an end date, let us say it is 2021-02-11 16:00:00.
I need to get the hours between these days which I do by using:
long diffInHours = TimeUnit.HOURS.convert(Math.abs(closeStoreDateTime.getTime() - openStoreDateTime.getTime()), TimeUnit.MILLISECONDS);
My issue is that as I iterate downward from the end date to the beginning date, I am converting the hour difference between the current hour and the beginning hour into an accurate time to store in a map later on. Like this:
int latestHour = (int) diffInHours;
while (latestHour >= openStoreDateTime.toInstant().atZone(ZoneId.systemDefault()).getHour()) {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(ZoneId.systemDefault()));
String hourConversion;
if (closeStoreDateTime.toInstant().atZone(ZoneId.systemDefault()).getDayOfYear() > openStoreDateTime.toInstant().atZone(ZoneId.systemDefault()).getDayOfYear()) {
if (latestHour > 24) {
calendar.add(Calendar.HOUR_OF_DAY, latestHour);
hourConversion = calendar.get(Calendar.AM_PM) == Calendar.AM ? String.valueOf(calendar.get(Calendar.HOUR)) : String.valueOf(calendar.get(Calendar.HOUR) + 12);
} else {
calendar.add(Calendar.HOUR_OF_DAY, latestHour);
int AM_PM = calendar.get(Calendar.AM_PM);
if (AM_PM == Calendar.AM || (AM_PM == Calendar.PM && calendar.get(Calendar.HOUR) == 12)) {
hourConversion = String.valueOf(calendar.get(Calendar.HOUR));
} else {
hourConversion = String.valueOf(calendar.get(Calendar.HOUR) + 12);
}
}
} else {
hourConversion = String.valueOf(latestHour);
}
This works if the dates are within the same year, but does not work if they are in different years because the day in the begin year (363) is greater than the day in the end year. Does anyone have an idea how to convert hours between 2 different dates into a useable date? Thank you.
If I understand your question correctly, you want a List of date-time values from an end date-time through a start date-time, one for each hour.
Here are some test results.
2021-02-11T16:00
2021-02-11T15:00
2021-02-11T14:00
2021-02-11T13:00
2021-02-11T12:00
...
2020-12-30T12:00
2020-12-30T11:00
2020-12-30T10:00
2020-12-30T09:00
2020-12-30T08:00
Here's runnable code that will do that using the LocalDateTime class. You can display a LocalDateTime value anyway you want using a DateTimeFormatter.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
public class DateIntervals {
public static void main(String[] args) {
String endDateString = "2021-02-11 16:00:00";
String startDateString = "2020-12-30 08:00:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"yyyy-MM-dd HH:mm:ss");
LocalDateTime endDate = LocalDateTime.parse(endDateString, formatter);
LocalDateTime startDate = LocalDateTime.parse(startDateString, formatter);
List<LocalDateTime> intervals = new ArrayList<>();
LocalDateTime date = endDate;
while (date.isAfter(startDate)) {
intervals.add(date);
date = date.minusHours(1L);
}
intervals.add(date);
for (int i = 0; i < intervals.size(); i++) {
System.out.println(intervals.get(i));
}
}
}
I want to write a boolean valued function which returns true if the given LocalDateTime falls between two specific points in time, false otherwise.
Specifically I want to have a LocalDateTime filter if a given date is between 22:00 GMT Friday and 23:00 GMT Sunday.
A skeleton could look like this:
public boolean isWeekend(LocalDateTime dateTime) {
//Checks if dateTime falls in between Friday's 22:00 GMT and Sunday's 23:00 GMT
//return ...???
}
This is basically a weekend filter and I'm wondering if there is a simple solution with the new Java 8 Time library(or any other existing filter methods).
I know how check for day of week, hour etc. but avoid to reinvent the wheel.
How would you expect such a library to work? You would still need to tell it when your weekend begins and ends and it would end up being not much shorter than the simple
boolean isWeekend(LocalDateTime dt) {
switch(dt.getDayOfWeek()) {
case FRIDAY:
return dt.getHour() >= ...;
case SATURDAY:
return true;
case SUNDAY:
return dt.getHour() < ...;
default:
return false;
}
}
A simple TemporalQuery would do the trick:
static class IsWeekendQuery implements TemporalQuery<Boolean>{
#Override
public Boolean queryFrom(TemporalAccessor temporal) {
return temporal.get(ChronoField.DAY_OF_WEEK) >= 5;
}
}
It would be called like this (using .now() to get a value to test):
boolean isItWeekendNow = LocalDateTime.now().query(new IsWeekendQuery());
Or, specifically in UTC time (using .now() to get a value to test):
boolean isItWeekendNow = OffsetDateTime.now(ZoneOffset.UTC).query(new IsWeekendQuery());
Going beyond your question, there is no reason to create a new instance of IsWeekendQuery every time it is used, so you might want to create a static final TemporalQuery that encapsulates the logic in a lambda expression:
static final TemporalQuery<Boolean> IS_WEEKEND_QUERY =
t -> t.get(ChronoField.DAY_OF_WEEK) >= 5;
boolean isItWeekendNow = OffsetDateTime.now(ZoneOffset.UTC).query(IS_WEEKEND_QUERY);
Temporal Query
The java.time framework includes an architecture for asking about a date-time value: Temporal Query. Some implementations of the TemporalQuery interface can be found in the plural-named TemporalQueries class.
You can write your own implementation as well. TemporalQuery is a functional interface, meaning it has a single method declared. The method is queryFrom.
This is my first attempt at implementing TemporalQuery, so take with a grain of salt. Here is the complete class. Free to use (ISC License), but entirely at your own risk.
The tricky part is the Question’s requirement is that the weekend be defined by UTC, not the time zone or offset of the passed date-time value. So we need to adjust the passed date-time value into UTC. While Instant is logically equivalent, I used OffsetDateTime with an offset of UTC as it is more flexible. Specifically the OffsetDateTime offers a getDayOfWeek method.
CAVEAT: I have no idea if I am doing things in an orthodox method as I do not completely comprehend the underpinnings of java.time’s designs as intended by its creators. Specifically I'm not sure if my casting of TemporalAccessor ta to a java.time.chrono.ChronoZonedDateTime is proper. But it seems to be working well enough.
It would be better if this class worked with Instant instances as well as ChronoZonedDateTime/ZonedDateTime.
package com.example.javatimestuff;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
/**
* Answers whether a given temporal value is between Friday 22:00 UTC
* (inclusive) and Sunday 23:00 UTC (exclusive).
*
* #author Basil Bourque.
*
* © 2016 Basil Bourque
* This source code may be used according to the terms of the ISC License (ISC). (Basically, do anything but sue me.)
* https://opensource.org/licenses/ISC
*
*/
public class WeekendFri2200ToSun2300UtcQuery implements TemporalQuery<Boolean> {
static private final EnumSet<DayOfWeek> WEEKEND_DAYS = EnumSet.of ( DayOfWeek.FRIDAY , DayOfWeek.SATURDAY , DayOfWeek.SUNDAY );
static private final OffsetTime START_OFFSET_TIME = OffsetTime.of ( LocalTime.of ( 22 , 0 ) , ZoneOffset.UTC );
static private final OffsetTime STOP_OFFSET_TIME = OffsetTime.of ( LocalTime.of ( 23 , 0 ) , ZoneOffset.UTC );
#Override
public Boolean queryFrom ( TemporalAccessor ta ) {
if ( ! ( ta instanceof java.time.chrono.ChronoZonedDateTime ) ) {
throw new IllegalArgumentException ( "Expected a java.time.chrono.ChronoZonedDateTime such as `ZonedDateTime`. Message # b4a9d0f1-7dea-4125-b68a-509b32bf8d2d." );
}
java.time.chrono.ChronoZonedDateTime czdt = ( java.time.chrono.ChronoZonedDateTime ) ta;
Instant instant = czdt.toInstant ();
OffsetDateTime odt = OffsetDateTime.ofInstant ( instant , ZoneOffset.UTC );
DayOfWeek dayOfWeek = odt.getDayOfWeek ();
if ( ! WeekendFri2200ToSun2300UtcQuery.WEEKEND_DAYS.contains ( dayOfWeek ) ) {
// If day is not one of our weekend days (Fri-Sat-Sun), then we know this moment is not within our weekend definition.
return Boolean.FALSE;
}
// This moment may or may not be within our weekend. Very early Friday or very late Sunday is not a hit.
OffsetDateTime weekendStart = odt.with ( DayOfWeek.FRIDAY ).toLocalDate ().atTime ( START_OFFSET_TIME ); // TODO: Soft-code with first element of WEEKEND_DAYS.
OffsetDateTime weekendStop = odt.with ( DayOfWeek.SUNDAY ).toLocalDate ().atTime ( STOP_OFFSET_TIME ); // TODO: Soft-code with last element of WEEKEND_DAYS.
// Half-Open -> Is equal to or is after the beginning, AND is before the ending.
// Not Before -> Is equal to or is after the beginning.
Boolean isWithinWeekend = ( ! odt.isBefore ( weekendStart ) ) && ( odt.isBefore ( weekendStop ) );
return isWithinWeekend;
}
static public String description () {
return "WeekendFri2200ToSun2300UtcQuery{ " + START_OFFSET_TIME + " | " + WEEKEND_DAYS + " | " + STOP_OFFSET_TIME + " }";
}
}
Let's use that TemporalQuery. While defining the TemporalQuery takes some work, using it is so very simple and easy:
Instantiate a TemporalQuery object.
Apply to our date-time object.(any instance of java.time.chrono.ChronoZonedDateTime in our case, such as ZonedDateTime)
In use.
WeekendFri2200ToSun2300UtcQuery query = new WeekendFri2200ToSun2300UtcQuery ();
I added a static description method for debugging and logging, to verify the query’s settings. This is my own invented method, not required by the TemporalQuery interface.
System.out.println ( "Weekend is: " + WeekendFri2200ToSun2300UtcQuery.description () );
First today, Tuesday. Should not be in weekend.
ZonedDateTime now = ZonedDateTime.now ( ZoneId.of ( "America/Montreal" ) );
Boolean nowIsWithinWeekend = now.query ( query );
System.out.println ( "now: " + now + " is in weekend: " + nowIsWithinWeekend );
Now with this Friday morning. Should not be in weekend.
ZonedDateTime friday1000 = ZonedDateTime.of ( LocalDate.of ( 2016 , 4 , 29 ) , LocalTime.of ( 10 , 0 ) , ZoneId.of ( "America/Montreal" ) );
Boolean friday1000IsWithinWeekend = friday1000.query ( query );
System.out.println ( "friday1000: " + friday1000 + " is in weekend: " + friday1000IsWithinWeekend );
And late on this Friday. Should be TRUE, within weekend.
ZonedDateTime friday2330 = ZonedDateTime.of ( LocalDate.of ( 2016 , 4 , 29 ) , LocalTime.of ( 23 , 30 ) , ZoneId.of ( "America/Montreal" ) );
Boolean friday2330IsWithinWeekend = friday2330.query ( query );
System.out.println ( "friday2330: " + friday2330 + " is in weekend: " + friday2330IsWithinWeekend );
When run.
Weekend is: WeekendFri2200ToSun2300UtcQuery{ 22:00Z | [FRIDAY, SATURDAY, SUNDAY] | 23:00Z }
now: 2016-04-26T20:35:01.014-04:00[America/Montreal] is in weekend: false
friday1000: 2016-04-29T10:00-04:00[America/Montreal] is in weekend: false
friday2330: 2016-04-29T23:30-04:00[America/Montreal] is in weekend: true
Local… does not mean local
Referring to the Question… saying you want to compare a LocalDateTime to values in UTC (the weekend start/stop) makes no sense. A LocalDateTime has no time zone of offset-from-UTC. While the naming may be counter-intuitive, Local… classes mean they could apply to any locality with no locality in particular. So they have no meaning, they are not a point on the timeline, until you apply a specify offset or time zone.
This entire Answer assumes you were confused about this terminology and did intend to compare an actual moment on the timeline.
I have written a small program to achieve this
PROGRAM
public class TestWeekend {
private static final int FRIDAY = 5;
private static final int SATURDAY = 6;
private static final int SUNDAY = 7;
private static final Integer WEEKEND_START_FRIDAY_CUT_OFF_HOUR = 22;
private static final Integer WEEKEND_END_SUNDAY_CUT_OFF_HOUR = 23;
private static List<Integer> weekendDaysList = Arrays.asList(FRIDAY, SATURDAY, SUNDAY);
public static void main(String []args) throws FileNotFoundException {
System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,22,18,39)));
System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,22,21,59)));
System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,22,22,0)));
System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,23,5,0)));
System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,24,8,0)));
System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,24,22,59)));
System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,24,23,0)));
System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,25,11,5)));
}
public static boolean isWeekend(LocalDateTime dateTime) {
System.out.print("Date - "+dateTime+" , ");
if(weekendDaysList.contains(dateTime.getDayOfWeek().getValue()) ){
if(SATURDAY == dateTime.getDayOfWeek().getValue()){
return true;
}
if(FRIDAY == dateTime.getDayOfWeek().getValue() && dateTime.getHour() >=WEEKEND_START_FRIDAY_CUT_OFF_HOUR){
return true;
}else if(SUNDAY == dateTime.getDayOfWeek().getValue() && dateTime.getHour() < WEEKEND_END_SUNDAY_CUT_OFF_HOUR ){
return true;
}
}
//Checks if dateTime falls in between Friday's 22:00 GMT and Sunday's 23:00 GMT
return false;
}
}
Hope this helps:
LocalDateTime localDateTime = LocalDateTime.now(DateTimeZone.UTC);
int dayNum = localDateTime.get(DateTimeFieldType.dayOfWeek());
boolean isWeekend = (dayNum == DateTimeConstants.SATURDAY || dayNum == DateTimeConstants.SUNDAY);
This is the simplest way for doing it without using many private constants.
Many good solutions are proposed, with Java 8+, found a simpler way if this can still help:
import static java.time.DayOfWeek.SATURDAY;
import static java.time.DayOfWeek.SUNDAY;
...
Set<DayOfWeek> WEEKEND = EnumSet.of(SATURDAY, SUNDAY);
public boolean isWeekend(LocalDateTime dateTime) {
return WEEKEND.contains(dateTime.getDayOfWeek());
}
An alternate Java 8+ solution would be to use a Predicate to test whether the date falls on a weekend.
Predicate<LocalDate> isWeekend = date -> DayOfWeek.from(date).get(ChronoField.DAY_OF_WEEK) > 5;
Then you can use apply it in a stream like
someListOfDates.stream()
.filter(isWeekend)
.forEach(System.out::println);
No external dependencies needed. (Though, please use a logger in production.)
I want set a (Gregorian) Calendar time to start-of-day April 1, 2016. I do this by setting month, day and year, and then setting all the time fields to their minimum values, giving me:
04/01/2016 12:00:00:000
If I subtract one millisecond I expect to get the last millisecond on the previous day, but instead I get the last millisecond on the same day:
04/01/2016 11:59:59:999
(Note: I get similar results if I subtract one second, minute or hour.)
What am I missing? Sample code follows, thanks.
package com.scg.domain;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class AdHoc
{
private static final int[] UNUSED_CAL_FIELDS =
{
Calendar.HOUR,
Calendar.MINUTE,
Calendar.SECOND,
Calendar.MILLISECOND
};
public static void main(String[] args)
{
Calendar cal = getGoodDate( Calendar.APRIL, 1,2016 );
System.out.println( cal.getCalendarType() );
adjustTime( "present", cal, 0 );
adjustTime( "past", cal, -1 );
adjustTime( "future", cal, 1 );
}
private static void adjustTime( String comment, Calendar cal, int incr )
{
Calendar newCal = Calendar.getInstance();
newCal.setTime( cal.getTime() );
newCal.add( Calendar.MILLISECOND, incr );
SimpleDateFormat fmt =
new SimpleDateFormat( "MM/dd/YYYY HH:mm:ss:SSS" );
System.out.println( comment + ": " + fmt.format( newCal.getTime() ) );
}
private static Calendar getGoodDate( int month, int day, int year )
{
Calendar cal = Calendar.getInstance();
cal.set( Calendar.YEAR, year );
cal.set( Calendar.MONTH, month );
cal.set( Calendar.DAY_OF_MONTH, day );
for ( int field : UNUSED_CAL_FIELDS )
cal.set( field, cal.getMinimum( field ) );
return cal;
}
}
You've used Calendar.HOUR, which controls only the 1-12 hour, not the 0-23 hour. Because of this, even though getMinimum returns 0, it's interpreted as 12:00 in whichever of AM or PM cal already is in, which must be PM from getInstance() (returns "now"). You really have 12:00 noon (PM). When you subtract a millisecond, it's still the same day.
To set it to midnight, try Calendar.HOUR_OF_DAY, which controls the 0-23 hour.
With this change, I get the output:
gregory
present: 04/01/2016 00:00:00:000
past: 03/31/2016 23:59:59:999
future: 04/01/2016 00:00:00:001
I want to get the day on which the first Monday of a specific month/year will be.
What I have:
I basically have two int variables, one representing the year and one representing the month.
What I want to have:
I want to know the first Monday in this month, preferably as an int or Integer value.
For example:
I have 2014 and 1 (January), the first Monday in this month was the 6th, so I want to return 6.
Problems:
I thought I could do that with the Calendar but I am already having trouble setting up the calendar with only Year and Month available. Furthermore, I'm not sure how to actually return the first Monday of the month/year with Calendar.
I already tried this:
Calendar cal = Calendar.getInstance();
cal.set(this.getYear(),getMonth(), 1);
int montag = cal.getFirstDayOfWeek();
for( int j = 0; j < 7; j++ ) {
int calc = j - montag;
if( calc < 0 ) {
calc += 6;
}
weekDays[calc].setText(getDayString(calc));
}
Java.time
Use java.time library built into Java 8 and TemporalAdjuster. See Tutorial.
import java.time.DayOfWeek;
import java.time.LocalDate;
import static java.time.temporal.TemporalAdjusters.firstInMonth;
LocalDate now = LocalDate.now(); //2015-11-23
LocalDate firstMonday = now.with(firstInMonth(DayOfWeek.MONDAY)); //2015-11-02 (Monday)
If you need to add time information, you may use any available LocalDate to LocalDateTime conversion like
firstMonday.atStartOfDay() # 2015-11-02T00:00
getFirstDayOfWeek() returns which day is used as the start for the current locale. Some people consider the first day Monday, others Sunday, etc.
This looks like you'll have to just set it for DAY_OF_WEEK = MONDAY and DAY_OF_WEEK_IN_MONTH = 1 as that'll give you the first Monday of the month. To do the same for the year, first set the MONTH value to JANUARY then repeat the above.
Example:
private static Calendar cacheCalendar;
public static int getFirstMonday(int year, int month) {
cacheCalendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
cacheCalendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
cacheCalendar.set(Calendar.MONTH, month);
cacheCalendar.set(Calendar.YEAR, year);
return cacheCalendar.get(Calendar.DATE);
}
public static int getFirstMonday(int year) {
return getFirstMonday(year, Calendar.JANUARY);
}
Here's a simple JUnit that tests it: http://pastebin.com/YpFUkjQG
First of all you should know the latest version of java i.e. JAVA8
Get familiar with LocalDate in JAVA8
Then only go through below code
public class Test {
public static void main(String[] args) {
LocalDate date=LocalDate.of(2014,1, 1);
for(int i=0;i<date.lengthOfMonth();i++){
if("Monday".equalsIgnoreCase(date.getDayOfWeek().toString())){
break;
}else{
date=date.plusDays(1);
}
}
System.out.println(date.getDayOfMonth());
}
}
Joda-Time
The Joda-Time library offers a class, LocalDate, for when you need only a date without a time-of-day. The method getDayOfWeek returns a number you can compare to the constant MONDAY.
LocalDate localDate = new LocalDate( year, month, 1 );
while ( localDate.getDayOfWeek() != DateTimeConstants.MONDAY ) {
localDate = localDate.plusDays( 1 );
}
int firstMonday = localDate.getDayOfMonth();
Immutable Syntax
For thread-safety, Joda-Time uses immutable objects. So rather than modify field values in an existing object, we create a new instance based on the original.
java.time
As another answer by Abhishek Mishra says, the new java.time package bundled with Java 8 also offers a LocalDate class similar to Joda-Time.
The method getFirstDayOfWeek() is not helpful. Quoting its javadoc:
Gets what the first day of the week is; e.g., SUNDAY in the U.S., MONDAY in France
The following tested method uses modulus arithmetic to find the day of the month of the first Monday:
public static long getMondaysDay(int year, int month) {
try {
Date d = new SimpleDateFormat("d-M-yyyy").parse("1-" + month + "-" + year);
long epochMillis = d.getTime() + TimeZone.getDefault().getOffset(d.getTime());
return (12 - TimeUnit.MILLISECONDS.toDays(epochMillis) % 7) % 7;
} catch (ParseException ignore) { return 0; } // Never going to happen
}
Knowing that the first day of the epoch was Thursday, this works by using modulus arithmetic to calculate the day of the epoch week, then how many days until the next Monday, then modulus again in case the first falls before Thursday. The magic number 12 is 4 (the number of days from Thursday to Monday) plus 1 because days of the month start from 1 plus 7 to ensure positive results after subtraction.
The simplest way is:
LocalDate firstSundayOfNextMonth = LocalDate
.now()
.with(firstDayOfNextMonth())
.with(nextOrSame(DayOfWeek.MONDAY));
Here is a general function to get the nth DAY_OF_WEEK of a given month. You can use it to get the first Monday of any given month.
import java.util.Calendar;
public class NthDayOfWeekOfMonth {
public static void main(String[] args) {
// get first Monday of July 2019
Calendar cal = getNthDayOfWeekOfMonth(2019,Calendar.JULY,1,Calendar.MONDAY);
System.out.println(cal.getTime());
// get first Monday of August 2019
cal = getNthDayOfWeekOfMonth(2019,Calendar.AUGUST,1,Calendar.MONDAY);
System.out.println(cal.getTime());
// get third Friday of September 2019
cal = getNthDayOfWeekOfMonth(2019,Calendar.SEPTEMBER,3,Calendar.FRIDAY);
System.out.println(cal.getTime());
}
public static Calendar getNthDayOfWeekOfMonth(int year, int month, int n, int dayOfWeek) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE,0);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.YEAR,year);
cal.set(Calendar.MONTH,month);
cal.set(Calendar.DAY_OF_MONTH,1);
int dayDiff = dayOfWeek-cal.get(Calendar.DAY_OF_WEEK);
if (dayDiff<0) {
dayDiff+=7;
}
dayDiff+=7*(n-1);
cal.add(Calendar.DATE, dayDiff);
return cal;
}
}
Output:
Mon Jul 01 00:00:00 EDT 2019
Mon Aug 05 00:00:00 EDT 2019
Fri Sep 20 00:00:00 EDT 2019
Lamma Date library is very good for this use case.
#Test
public void test() {
assertEquals(new Date(2014, 1, 6), firstMonday(2014, 1));
assertEquals(new Date(2014, 2, 3), firstMonday(2014, 2));
assertEquals(new Date(2014, 3, 3), firstMonday(2014, 3));
assertEquals(new Date(2014, 4, 7), firstMonday(2014, 4));
assertEquals(new Date(2014, 5, 5), firstMonday(2014, 5));
assertEquals(new Date(2014, 6, 2), firstMonday(2014, 6));
}
public Date firstMonday(int year, int month) {
Date firstDayOfMonth = new Date(year, month, 1);
return firstDayOfMonth.nextOrSame(DayOfWeek.MONDAY);
}
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("MMM/dd/YYYY");
calendar.set(Calendar.MONTH,Calendar.JUNE);
calendar.set(Calendar.DAY_OF_MONTH,1);
int day = (Calendar.TUESDAY-calendar.get(Calendar.DAY_OF_WEEK));
if(day<0){
calendar.add(Calendar.DATE,7+(day));
}else{
calendar.add(Calendar.DATE,day);
}
System.out.println("First date is "+sdf.format(calendar.getTime()));
Get the All Monday of a month
public class AllMonday {
public static void main(String[] args){
System.out.println(weeksInCalendar(YearMonth.now()));
}
public static List<LocalDate> weeksInCalendar(YearMonth month) {
List<LocalDate> firstDaysOfWeeks = new ArrayList<>();
for (LocalDate day = firstDayOfCalendar(month);
stillInCalendar(month, day); day = day.plusWeeks(1)) {
firstDaysOfWeeks.add(day);
}
return firstDaysOfWeeks;
}
private static LocalDate firstDayOfCalendar(YearMonth month) {
DayOfWeek FIRST_DAY_OF_WEEK = DayOfWeek.of(1);
System.out.println( month.atDay(1).with(FIRST_DAY_OF_WEEK));
return month.atDay(1).with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
}
private static boolean stillInCalendar(YearMonth yearMonth, LocalDate day) {
System.out.println(!day.isAfter(yearMonth.atEndOfMonth()));
return !day.isAfter(yearMonth.atEndOfMonth());
}
}
If I have a date of an event, such as 2011-01-03, how to detect if it is within this or next week in java ? Any sample code ?
Edit :
I thought it was a simple question, it turned out more complex than I thought, what I meat this week is : from this past Sun to this Sat, next week is from next Sun to the Sat after that.
It partly depends on what you mean by "this week" and "next week"... but with Joda Time it's certainly easy to find out whether it's in "today or the next 7 days" as it were:
LocalDate event = getDateFromSomewhere();
LocalDate today = new LocalDate();
LocalDate weekToday = today.plusWeeks(1);
LocalDate fortnightToday = weekToday.plusWeeks(1);
if (today.compareTo(event) <= 0 && event.compareTo(weekToday) < 0)
{
// It's within the next 7 days
}
else if (weekToday.compareTo(event) <= 0 && event.compareTo(fornightToday) < 0)
{
// It's next week
}
EDIT: To get the Sunday to Saturday week, you'd probably want:
LocalDate startOfWeek = new LocalDate().withDayOfWeek(DateTimeConstants.SUNDAY);
then do the same code as the above, but relative to startOfWeek.
How about this :
Calendar c=Calendar.getInstance();
c.set(Calendar.DAY_OF_WEEK,Calendar.SUNDAY);
c.set(Calendar.HOUR_OF_DAY,0);
c.set(Calendar.MINUTE,0);
c.set(Calendar.SECOND,0);
DateFormat df=new SimpleDateFormat("EEE yyyy/MM/dd HH:mm:ss");
System.out.println(df.format(c.getTime())); // This past Sunday [ May include today ]
c.add(Calendar.DATE,7);
System.out.println(df.format(c.getTime())); // Next Sunday
c.add(Calendar.DATE,7);
System.out.println(df.format(c.getTime())); // Sunday after next
The result :
Sun 2010/12/26 00:00:00
Sun 2011/01/02 00:00:00
Sun 2011/01/09 00:00:00
Any day between the first two is this week, anything between the last two is next week.
Although old question - is still relevant. The most upvoted answer here is correct wrt to Joda-time and wrt to JDK8 as well with some syntax changes. Here's one that might help those who are looking around in JDK8 world.
public static boolean isLocalDateInTheSameWeek(LocalDate date1, LocalDate date2) {
LocalDate sundayBeforeDate1 = date1.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
LocalDate saturdayAfterDate1 = date1.with(TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY));
return ((date2.isEqual(sundayBeforeDate1) || date2.isAfter(sundayBeforeDate1))
&& (date2.isEqual(saturdayAfterDate1) || date2.isBefore(saturdayAfterDate1)));
}
Most answers here do not satisfy me. They either use the outdated Calendar-API (excusable in old answers given in times before Java 8, and it is hence not fair to criticize such answers), or they are even partially wrong or unnecessarily complex. For example, the most upvoted answer by Jon Skeet suggests to determine the first day of week by the Joda-expression new LocalDate().withDayOfWeek(DateTimeConstants.SUNDAY). But such code uses the ISO-definition of a week starting on Monday with the consequence that if the current date is not on Sunday the code would produce next Sunday and not previous Sunday as desired by the OP. Joda-Time is incapable of handling non-ISO weeks.
Another minor flaw of other answers is not to care about if the current AND NEXT week contains a given date - as requested by the OP. So here my improved suggestion in modern Java:
LocalDate today = LocalDate.now(); // involves the system time zone and clock of system
LocalDate startOfCurrentWeek =
today.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
LocalDate endOfNextWeek =
startOfCurrentWeek.plusDays(13);
LocalDate event = LocalDate.of(2011, 1, 3); // input of example given by OP
boolean matchingResult =
!(event.isBefore(startOfCurrentWeek) || event.isAfter(endOfNextWeek));
Side note: The question has inspired me to add a small enhancement to the class DateInterval in my library Time4J how to determine the current calendar week in a very generic way.
Hint: use Calendar. Create new instance of it for your sample event date. Then, compare WEEK_OF_YEAR for current date, and the date of your event.
for those that has to stick to JDK 7 and can't use joda.time, I wrote this method and tested.
public static boolean inSameWeek(Date date1, Date date2) {
if (null == date1 || null == date2) {
return false;
}
Calendar earlier = Calendar.getInstance();
Calendar later = Calendar.getInstance();
if (date1.before(date2)) {
earlier.setTime(date1);
later.setTime(date2);
} else {
earlier.setTime(date2);
later.setTime(date1);
}
if (inSameYear(date1, date2)) {
int week1 = earlier.get(Calendar.WEEK_OF_YEAR);
int week2 = later.get(Calendar.WEEK_OF_YEAR);
if (week1 == week2) {
return true;
}
} else {
int dayOfWeek = earlier.get(Calendar.DAY_OF_WEEK);
earlier.add(Calendar.DATE, 7 - dayOfWeek);
if (inSameYear(earlier.getTime(), later.getTime())) {
int week1 = earlier.get(Calendar.WEEK_OF_YEAR);
int week2 = later.get(Calendar.WEEK_OF_YEAR);
if (week1 == week2) {
return true;
}
}
}
return false;
}
public static boolean inSameYear(Date date1, Date date2) {
if (null == date1 || null == date2) {
return false;
}
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
int year1 = cal1.get(Calendar.YEAR);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
int year2 = cal2.get(Calendar.YEAR);
if (year1 == year2)
return true;
return false;
}
You can use the Calendar API to retrieve the week for a given day.
Calendar cal = Calendar.getInstance();
cal.setTime(somedate);
int week = cal.get(Calendar.WEEK_OF_YEAR);
tl;dr
Testing a pair of LocalDate objects by using org.threeten.extra.LocalDateRange class with a TemporalAdjuster named ta that determines the first day of the week.
LocalDateRange.of(
localDate1.with( ta ) ,
localDate1.with( ta ).plusWeeks( 1 )
)
.contains(
localDate2
)
ThreeTen-Extra
The ThreeTen-Extra project adds additional functionality to the java.time classes built into Java (defined by JSR 310).
Among the added classes is LocalDateRange. This class represents a span-of-time attached to the timeline. In other words, a pair of LocalDate objects. This class offers handy methods for comparing, such as overlaps, contains, and abuts. Here we need equals.
Define a method where you pass your two dates plus the first day of the week (a DayOfWeek enum object).
We use a TemporalAdjuster found in the TemporalAdjusters class to determine the date of the first day of the week. Then add a week to get the end of the week (per Half-Open definition of a span-of-time).
We could be cute and check to see if both dates are the same. A worthy check if such a case is likely often in your app.
For week 2, let's use a one-liner as alternative syntax.
public boolean inSameWeek ( LocalDate localDate1 , LocalDate localDate2 , DayOfWeek firstDayOfWeek ) {
Objects.requireNonNull( localDate1 ) ; // … ditto for other arguments.
if( localDate1.isEqual( localDate2 ) ) { return true ; }
TemporalAdjuster ta = TemporalAdjusters.previousOrSame( firstDayOfWeek ) ;
LocalDate weekStart1 = localDate1.with( ta ) ;
LocalDate weekStop1 = weekStart1.plusWeeks( 1 ) ;
LocalDateRange week1 = LocalDateRange.of( weekStart1 , weekStop1 ) ;
LocalDateRange week2 =
LocalDateRange.of(
localDate2.with( ta ) ,
localDate2.with( ta ).plusWeeks( 1 )
)
;
// Compare the weeks.
return week1.equals( week2 ) ;
}
Or even more compact.
public boolean inSameWeek ( LocalDate localDate1 , LocalDate localDate2 , DayOfWeek firstDayOfWeek ) {
Objects.requireNonNull( localDate1 ) ; // … ditto for other arguments.
if( localDate1.isEqual( localDate2 ) ) { return true ; }
TemporalAdjuster ta = TemporalAdjusters.previousOrSame( firstDayOfWeek ) ;
return
LocalDateRange.of(
localDate1.with( ta ) ,
localDate1.with( ta ).plusWeeks( 1 )
)
.equals(
LocalDateRange.of(
localDate2.with( ta ) ,
localDate2.with( ta ).plusWeeks( 1 )
)
)
;
}
We really do not need that second week. We only care if the first determined week contains the second passed date argument.
public boolean inSameWeek ( LocalDate localDate1 , LocalDate localDate2 , DayOfWeek firstDayOfWeek ) {
Objects.requireNonNull( localDate1 ) ; // … ditto for other arguments.
if( localDate1.isEqual( localDate2 ) ) { return true ; }
TemporalAdjuster ta = TemporalAdjusters.previousOrSame( firstDayOfWeek ) ;
return
LocalDateRange.of(
localDate1.with( ta ) ,
localDate1.with( ta ).plusWeeks( 1 )
)
.contains(
localDate2
)
;
}
Use it.
LocalDate localDate = LocalDate.of( 2019 , Month.JANUARY , 23 ) ;
LocalDate today = LocalDate.now( ZoneId.of( "Africa/Tunis") ) ;
boolean sameWeek = this.inSameWeek( localDate , today , DayOfWeek.SUNDAY ) ;
Caveat: I ran none of this code.
This is what worked for me in Java 8
import java.time.LocalDate;
LocalDate today = LocalDate.now();
LocalDate twoWeeksBefore = today.minusWeeks(2);
LocalDate checkDate = someObject.getSomeDate();
if(checkDate.compareTo(twoWeeksBefore) > 0) {
// do something if checkDate is within last two weeks
} else {
// do something if checkDate is on or before last two weeks
}