Less than or equal to with GregorianCalendar - java

i have this code in my program:
if (expire.after(start) && expire.before(end))
//do somethig
But this code does not include the bound day.
I mean for example if start is 2014/01/15, end is 2014/01/20 and expire is 2014/01/20, expire is not considered. How to solve?
I tried in this way:
if (expire.after(start) && (expire.equals(end) || expire.before(end)))
But it doesn't work, i get the same result.

As #assylias stated you might try !expire.after(end) although this is probably not enough. If you instead use expire.equals(end) then you have to keep in mind that this is not just a temporal comparison! Here you also compare time zone informations, even the locale and so on. In general it is not good to use GregorianCalendar for only date comparisons because this type also knows milliseconds as time part. So you have probably either to manually set the whole time part of all three calendar instances to zero (midnight, leaving out time zone anomalies like in Brazil at certain days) or much better, you should instead extract the date informations and compare these details by using following tool:
public class DateComparator implements Comparator<GregorianCalendar> {
public int compare(GregorianCalendar gcal1, GregorianCalendar gcal2) {
int y1 = gcal1.get(Calendar.YEAR);
int y2 = gcal2.get(Calendar.YEAR);
if (y1 != y2) {
return y1 - y2;
}
int m1 = gcal1.get(Calendar.MONTH);
int m2 = gcal2.get(Calendar.MONTH);
if (m1 != m2) {
return m1 - m2;
}
return gcal1.get(Calendar.DATE) - gcal2.get(Calendar.DATE);
}
}
But make sure that you always have the same time zone when comparing the date parts.
Otherwise you can try JodaTime which offers the type LocalDate. And a similar date-only type is also contained in new Java 8.

When I have done time checks in the past I always used only after and before, even when I has a range check that was start <= current <= end.
You achieve this by adjusting the start and end dates such that they are outside the bounds of the desired range.
For example, if the start date is 2014/01/15, then use the start date value of 2014/01/14 23:59:59 as the actual start date that is used for the comparison. For the end date, instead of 2014/01/20, use 2014/01/21 00:00:00. With these values you can use .after(startDate) and .before(endDate).
Here is some code to calculate the start date:
private static Date calculateStartDate(
final int year,
final int month,
final int dayOfMonth)
{
Calendar calendar = Calendar.getInstance();
Date returnValue;
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
calendar.set(Calendar.HOUR, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
returnValue = calendar.getTime();
return returnValue;
}
Edit added millisecond above

Or
if ((expire.compareTo(start) >= 0) && (expire.compareTo(end) <= 0))
since
http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#after(java.lang.Object)
says .before is equivalent to compareTo(when) < 0 and .after is equivalent to compareTo(when) > 0

I finally solved adjusting the start and end dates such that they are outside the bounds of the desired range.
For example, if the start date is 2014/01/15, i set it to 2014/01/14 and if the end date is 2014/01/20, i set it to 2014/01/21. With these values i can use .after and .before methods with no problems.
Thank you to DwB for the suggestion and than you to all for your great support!

tl;dr
Use java.time.LocalDate for a date-only value.
( ! ( myLocalDate.isBefore( start ) ) // Is target date NOT before the start (meaning, is the target equal to or later than
&&
myLocalDate.isBefore( stop )
…or, better:
org.threeten.extra.LocalDateRange.of( // Half-Open range.
LocalDate.of( 2014 , Month.JANUARY , 15 ) , // Inclusive.
LocalDate.of( 2014 , Month.JANUARY , 20 ) // Exclusive.
).contains(
LocalDate.of( 2014 , Month.JANUARY , 11 )
)
false
GregorianCalendar is a troublesome obsolete class. Avoid it.
Details
I do not understand the logic of your business problem, but perhaps this example code will help.
I believe you'll find that working with time spans in the "half-open" approach works best. The start of the span is inclusive, and the ending is exclusive. For more discussion see another answer of mine with this chart…
java.time
Here is some code using the modern java.time classes built into Java 8 and later.
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.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
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(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. 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.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Comparing dates
The LocalDate class offers comparison methods: isBefore, isAfter, isEqual, equals, and compareTo.
Not exactly sure from your Question what your comparison rules are. But I guess you are missing the concept of using the ! operator for "NOT" condition.
Using the Half-Open approach we want to ask if the target date "is equal to or later than the beginning AND before than ending".
LocalDate start = LocalDate.of( 2014 , Month.JANUARY , 15 ) ;
LocalDate stop = LocalDate.of( 2014 , Month.JANUARY , 20 ) ;
boolean rangeContainsTarget = ( ld.isEqual( start ) || (ld.isAfter( start ) ) && ld.isBefore( stop ) ; // Half-Open test, the long-way. "is equal to or later than the beginning AND before than ending"
A shorter way to ask "is equal to or later than" is "is not before".
boolean rangeContainsTarget = ( ! ( ld.isBefore( start ) ) && ld.isBefore( stop ) ; // Half-Open test, the long-way. "is not before the beginning AND before than ending"
Range object
Add the ThreeTen-Extra library to your project to access the LocalDateRange class. It defines a range of time as a pair of LocalDate objects. The class offers handy methods such as abuts, contains, intersection, and more. It uses the Half-Open approach.
LocalDateRange range = LocalDateRange.of( start , stop ) ;
boolean rangeContainsTarget = range.contains( target ) ;
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
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, 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.
Joda-Time
UPDATE: The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. This section left intact for history.
Look at this code using the Joda-Time 2.3 library.
// Specify a time zone rather than rely on default.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Oslo" );
DateTime event = new DateTime( 2014, 1, 20, 23, 59, 59, timeZone );
DateTime begin = new DateTime( 2014, 01, 15, 0, 0, 0, timeZone ); // Inclusive
// After the stroke of midnight of the 20th, on the first moment of the new day (the 21st), event is late.
DateTime end = new DateTime( 2014, 01, 21, 0, 0, 0, timeZone ); // Exclusive. All split-second moments before this are acceptable, but this moment and onwards is not acceptable.
Interval interval = new Interval( begin, end );
boolean isEventOnSchedule = interval.contains( event );
Dump to console…
System.out.println( "event: " + event );
System.out.println( "begin: " + begin );
System.out.println( "end: " + end );
System.out.println( "interval: " + interval );
System.out.println( "isEventOnSchedule: " + isEventOnSchedule );
When run…
event: 2014-01-20T23:59:59.000+01:00
begin: 2014-01-15T00:00:00.000+01:00
end: 2014-01-21T00:00:00.000+01:00
interval: 2014-01-15T00:00:00.000+01:00/2014-01-21T00:00:00.000+01:00
isEventOnSchedule: true

Related

Calendar set() broken on Android API 23 and below - java.util.Calendar

I am using java.util.Calendar to find the start of a given week using its set() methods.
This works perfectly on Android Nougat+, but not on any Android version below Marshmallow.
I have tested on both physical devices and emulators.
I have used the debugger to verify that the problem lies with the Calendar code, not some issue in displaying it.
I have used Kotlin and Java to create different minimal examples, and the issue persists in both.
Here is the Kotlin minimal example, where a TextView displays the date and a Button is used to increase that date by a week:
class MainActivity : AppCompatActivity() {
var week = 10
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Set TextView to show the date of the 10th week in 2018.
setCalendarText(week)
// Increase the week on every button click, and show the new date.
button.setOnClickListener { setCalendarText(++week) }
}
/**
* Set the text of a TextView, defined in XML, to the date of
* a given week in 2018.
*/
fun setCalendarText(week: Int) {
val cal = Calendar.getInstance().apply {
firstDayOfWeek = Calendar.MONDAY
set(Calendar.YEAR, 2018)
set(Calendar.WEEK_OF_YEAR, week)
set(Calendar.DAY_OF_WEEK, Calendar.MONDAY)
set(Calendar.HOUR_OF_DAY, 0)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 1)
}
textView.text = SimpleDateFormat("dd MMMM yyyy", Locale.UK).format(cal.time)
}
}
When working as expected, the activity launches with the TextView set to display "05 March 2018". This value changes to the first day of every successive week when the button is clicked.
On Android Marshmallow and below:
The TextView's initial value is set to the start of the current week (03 September 2018).
The date does not change when the button is clicked.
The Calendar can correctly retrieve the last day of the current week if the day is set to Calendar.SUNDAY. It will not work for any other weeks.
Edit: I have attempted to create a Java MVCE, which allows you to perform a quick check whether the basic problem appears by running CalendarTester.test().
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
class CalendarTester {
/**
* Check that the Calendar returns the correct date for
* the start of the 10th week of 2018 instead of returning
* the start of the current week.
*/
public static void test() {
// en_US on my machine, but should probably be en_GB.
String locale = Locale.getDefault().toString();
Log.v("CalendarTester", "The locale is " + locale);
Long startOfTenthWeek = getStartOfGivenWeek(10);
String startOfTenthWeekFormatted = formatDate(startOfTenthWeek);
boolean isCorrect = "05 March 2018".equals(startOfTenthWeekFormatted);
Log.v("CalendarTester", String.format("The calculated date is %s, which is %s",
startOfTenthWeekFormatted, isCorrect ? "CORRECT" : "WRONG"));
}
public static Long getStartOfGivenWeek(int week) {
Calendar cal = Calendar.getInstance();
cal.setFirstDayOfWeek(Calendar.MONDAY);
cal.set(Calendar.YEAR, 2018);
cal.set(Calendar.WEEK_OF_YEAR, week);
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 1);
return cal.getTimeInMillis();
}
public static String formatDate(Long timeInMillis) {
return new SimpleDateFormat("dd MMMM yyyy", Locale.UK).format(timeInMillis);
}
}
tl;dr
Use the java.time classes back-ported to early Android.
Problem statement: From current date, move to previous or same Monday, then move to Monday of standard ISO 8601 week number 10 of that date’s week-based year, add one week, and generate text in standard ISO 8601 format for the resulting date.
org.threeten.bp.LocalDate.now( // Represent a date-only value, without time-of-day and without time zone.
ZoneId.of( "Europe/London" ) // Determining current date requires a time zone. For any given moment, the date and time vary around the globe by zone.
) // Returns a `LocalDate`. Per immutable objects pattern, any further actions generate another object rather than changing (“mutating”) this object.
.with(
TemporalAdjusters.previousOrSame( // Move to another date.
DayOfWeek.MONDAY // Specify desired day-of-week using `DayOfWeek` enum, with seven objects pre-defined for each day-of-week.
)
) // Renders another `LocalDate` object.
.with(
IsoFields.WEEK_OF_WEEK_BASED_YEAR ,
10
)
.plusWeeks( 1 )
.toString()
2018-03-12
Simplify the problem
When tracking down mysterious or buggy behavior, simply the programming to the barest minimum needed to reproduce the problem. In this case, strip away the supposedly irrelevant GUI code to focus on the date-time classes.
As in a scientific experiment, control for various variables. In this case, both time zone and Locale affect the behavior of Calendar. For one thing, the definition of a week within Calendar varies by Locale. So specify these aspects explicitly by hard-coding.
Set a specific date and time, as different times on different days in different zones can affect the behavior.
Calendar is a superclass with various implementations. If you are expecting GregorianCalendar, use that explicitly while debugging.
So, trying running something like the following across your tool scenarios to troubleshoot your problem.
TimeZone tz = TimeZone.getTimeZone( "America/Los_Angeles" );
Locale locale = Locale.US;
GregorianCalendar gc = new GregorianCalendar( tz , locale );
gc.set( 2018 , 9- 1 , 3 , 0 , 0 , 0 ); // Subtract 1 from month number to account for nonsensical month numbering used by this terrible class.
gc.set( Calendar.MILLISECOND , 0 ); // Clear fractional second.
System.out.println( "gc (original): " + gc.toString() );
System.out.println( gc.toZonedDateTime() + "\n" ); // Generate a more readable string, using modern java.time classes. Delete this line if running on Android <26.
int week = 10;
gc.set( Calendar.WEEK_OF_YEAR , week );
System.out.println( "gc (week=10): " + gc.toString() );
System.out.println( gc.toZonedDateTime() + "\n" );
int weekAfter = ( week + 1 );
gc.set( Calendar.WEEK_OF_YEAR , weekAfter );
System.out.println( "gc (weekAfter): " + gc.toString() );
System.out.println( gc.toZonedDateTime() + "\n" );
When run.
gc (original): java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2018,MONTH=8,WEEK_OF_YEAR=36,WEEK_OF_MONTH=2,DAY_OF_MONTH=3,DAY_OF_YEAR=251,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=2,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-28800000,DST_OFFSET=3600000]
2018-09-03T00:00-07:00[America/Los_Angeles]
gc (week=10): java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2018,MONTH=8,WEEK_OF_YEAR=10,WEEK_OF_MONTH=2,DAY_OF_MONTH=3,DAY_OF_YEAR=246,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-28800000,DST_OFFSET=3600000]
2018-03-05T00:00-08:00[America/Los_Angeles]
gc (weekAfter): java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2018,MONTH=2,WEEK_OF_YEAR=11,WEEK_OF_MONTH=2,DAY_OF_MONTH=5,DAY_OF_YEAR=64,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-28800000,DST_OFFSET=0]
2018-03-12T00:00-07:00[America/Los_Angeles]
java.time
Really, your problem is moot because you should not be using the terrible old Calendar class at all. It is part of the troublesome old date-time classes that years ago were supplanted by the modern java.time classes. For early Android, see the last bullets at bottom below.
In Calendar/GregorianCalendar, the definition of a week varies by Locale, Not so in java.time by default, which uses the ISO 8601 standard definition of a week.
Week # 1 has the first Thursday of the calendar-year.
Monday is the first day of the week.
A week-based year has either 52 or 53 weeks.
The first/last few days of the calendar may appear in the previous/next week-based year.
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.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
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(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. 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.
LocalDate ld = LocalDate.of( 2018 , Month.SEPTEMBER , 3 ) ;
TemporalAdjuster
To move to a prior Monday, or stay on the date if already a Monday, use a TemporalAdjuster implementation provided in the TemporalAdjusters class. Specify desired day-of-week with DayOfWeek enum.
LocalDate monday = ld.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) ) ;
IsoFields
The java.time classes have limited support for weeks. Use the IsoFields class with its constants WEEK_OF_WEEK_BASED_YEAR & WEEK_BASED_YEAR.
LocalDate mondayOfWeekTen = monday.with( IsoFields.WEEK_OF_WEEK_BASED_YEAR , 10 ) ;
ISO 8601
The ISO 8601 standard defines many useful practical formats for representing date-time values as text. This includes weeks. Let's generate such text as output.
String weekLaterOutput =
weekLater
.get( IsoFields.WEEK_BASED_YEAR )
+ "-W"
+ String.format( "%02d" , weekLater.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) )
+ "-"
+ weekLater.getDayOfWeek().getValue()
; // Generate standard ISO 8601 output. Ex: 2018-W11-1
Dump to console.
System.out.println("ld.toString(): " + ld);
System.out.println("monday.toString(): " +monday);
System.out.println("weekLater.toString(): " + weekLater);
System.out.println( "weekLaterOutput: " + weekLaterOutput ) ;
When run.
ld.toString(): 2018-09-03
monday.toString(): 2018-09-03
weekLater.toString(): 2018-03-12
weekLaterOutput: 2018-W11-1
Tip for Java (not Android): If doing much work with weeks, consider adding the ThreeTen-Extra library to access its YearWeek class.
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….

Compare Date and Time in Java

how to compare three date/time values in java?
Currently i use Date objects
I mean:
Date1 - today, 10:00PM
Date2 - tomorrow, 5:00AM
Date3 - current time
Is date3 between date1 and date2, respect date AND time?
date1.compareTo(date3) * date2.compareTo(date3) > 0
and
date1.after(date3) && date2.before(date3)
are not working.
I use this code in Android App, and if i set my time to 11.30AM, it still returns true for above conditions. If i use Time-objects and 2nd method, it doesn't recognise my time span is between 2 days.
Any idea?
EDIT: To make it exact, here is my current code. app is something like an alarm clock.
// Current Date/Time
Date now = Calendar.getInstance().getTime();
// Time when user goes to bed (current day)
Date sleep = new Date(now.getYear(), now.getMonth(), now.getDate(), Shours, Sminutes);
// Time when user wakes up (next day)
// Get Next Day's Date and set Time
Calendar wk = Calendar.getInstance();
wk.setTime(sleep);
wk.set(Calendar.HOUR_OF_DAY, Whours);
wk.set(Calendar.MINUTE, Wminutes);
// tomorrow
wk.add(Calendar.DATE, 1);
// and convert to date
Date wake = wk.getTime();
// Compare
if(now.after(sleep) && now.before(wake)) {
Log.d("uSleep", "Debug: Night time");
}
else {
Log.d("uSleep", "Debug: Day Time");
}
Maybe it's still too hard to understand. Image you go to bed at 10PM and you get up at 5AM. Now how to find out if you're sleeping by comparing your "go to bed"-time and you "get up"-time to the current time. I need to use "tomorrow" for your "get up"-time, otherwise java seems to compare all times for the same day, which is impossible.
tl;dr
Interval.of(
start ,
stop
).contains(
ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )
.toInstant()
)
Details
The question is confusing, but seems to be…
How do I tell if a particular moment occurs within a span of time?
java.time
I mean: Date1 - today, 10:00PM Date2 - tomorrow, 5:00AM Date3 - current time
A time zone is crucial in determining “today” and “tomorrow”. 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(!).
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( z );
To get the same date with another time-of-day, extract LocalDate. The LocalDate class represents a date-only value without time-of-day and without time zone. Specify desired time-of-day with LocalTime. Combine with ZoneId to get a ZonedDateTime.
LocalDate today = now.toLocalDate() ;
LocalTime tenPm = LocalTime.of( 22 , 0 ) ; // 10 PM is 22:00.
ZonedDateTime tenPmToday = ZonedDateTime.of( today , tenPm , z ) ;
To get tomorrow, add one day to today's date.
LocalDate tomorrow = ld.plusDays( 1 ) ;
LocalTime fiveAm = LocalTime.of( 5 , 0 ) ;
ZonedDateTime fiveAmTomorrow = ZonedDateTime.of( tomorrow ,fiveAm , z ) ;
Compare
To compare, call the isBefore, isEqual, and isAfter methods.
Boolean contains = ( ! now.isBefore( tenPmToday ) ) && now.isBefore( fiveAmTomorrow ) ;
Of course, now will always be before tomorrow, so I'm not sure of your intentions here.
org.threeten.extra.Interval
You may find the Interval class useful for this work, from the ThreeTen-Extra project listed below. This class stores a pair of Instant objects, and has some handy comparison methods such as contains.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Interval interval = Interval.of( tenPmToday.toInstant() , fiveAmTomorrow.toInstant() ) ;
Boolean contains = interval.contains( now.toInstant() ) ;
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.
Joda-Time
Update: the Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes.
The best way is to use the Joda-Time library, rather than the java.util.Date/.Calendar classes which are notoriously troublesome, confusing, and flawed.
Span Of Time
In Joda-Time you can represent a span of time in three ways: Interval, Period, and Duration. In this case, we need Interval, defined by a pair of specific points in the timeline, with the half-open [) approach where the beginning is inclusive and the ending exclusive.
The pair of specific points, as well as the current moment now, are all represented by the DateTime class. Unlike a java.util.Date, a DateTime knows its own assigned time zone. If unspecified, the JVM’s current default time zone will be applied. So generally better to specify.
Example Code
Some example code using Joda-Time 2.5.
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zone );
DateTime bedtime = now.withTime( 22, 0, 0, 0 ); // Today’s bedtime. May be past, future, or this very moment now.
DateTime risetime = bedtime.plusHours( 7 ); // 05:00 next morning.
Interval sleepInterval = new Interval( bedtime, risetime );
boolean asleep = sleepInterval.contains( now ); // Half-Open "[)" comparison, beginning is inclusive, ending exclusive.

What's the difference between adding DAY_OF_MONTH or DAY_OF_YEAR to a Calendar object?

I want to increase a certain date by 1 day. I create a Calendar object like:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2012);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 31);
Then, for increasing it by 1 day, I can do 2 things :
cal.add(Calendar.DAY_OF_MONTH, 1);
OR
cal.add(Calendar.DAY_OF_YEAR, 1);
There are also other "DAY" constants, but I get the same result using the above 2 methods of increasing the day by 1. In which case will I get different results for the two?
For adding it really makes no difference, but this
Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.DAY_OF_MONTH));
System.out.println(c.get(Calendar.DAY_OF_YEAR));
prints
28
363
Calendar.add Adds or subtracts the specified amount of time to the given calendar field, based on the calendar's rules.
Here you have a list of the fields of Calendar that you can add or subtract:
MILLISECOND is the number of milliseconds between 0 and 999
SECOND is the number of seconds between 0 and 59
MINUTE is the number of minutes between 0 and 59
HOUR is the number of hours between 0 and 11
HOUR_OF_DAY is the number of hours between 0 and 23
DAY_OF_WEEK is the day in relation of the week between 1 and 7
DAY_OF_MONTH is the day in relation of the month between 1 and 31
DAY_OF_YEAR is the day in relation of the year between 1 and 366
WEEK_OF_MONTH is the week in relation of the month starting from 1
WEEK_OF_YEAR is the week in relation of the year starting from 1
MONTH is the month in relation of the year between 0 and 11
YEAR is the number of years starting from 1
Hours, days and weeks have multiple fields but it doesn't matter which one you choose1. For example using -8 for DAY_OF_WEEK will work.
calendar.add(Calendar.DAY_OF_MONTH, -2); // subtract 2 days
calendar.add(Calendar.DAY_OF_WEEK, -2); // subtract 2 days
calendar.add(Calendar.DAY_OF_YEAR, -2); // subtract 2 days
calendar.add(Calendar.YEAR, -2); // subtract 2 years
1It doesn't matter only using Calendar.add, with other operations the results might be different.
Use Calendar.DATE for your purposes. In your case these three constants are synonyms.
It doesn't make any difference when you call add. However the getters return different results :D
code snippet from GregorianCalendar#add
case DAY_OF_MONTH: // synonym of DATE
case DAY_OF_YEAR:
case DAY_OF_WEEK:
break;
DAY_OF_YEAR
Field number for get and set indicating the day number within the current year
DAY_OF_MONTH
Field number for get and set indicating the day of the month. This is a synonym for DATE
You will see difference if the day is greater than 31.
You essentially advance the date by one, in both the cases. So there is no difference in both the approaches.
But sticking to a single method will render consistency across your codebase, maintainers will feel at home and probably the runtime optimizes the method call by compiling it as well.
Actually, there can and will be a difference depending on what field type you choose:
*
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html
Usage model.
To motivate the behavior of add() and roll(), consider a
user interface component with increment and decrement buttons for the
month, day, and year, and an underlying GregorianCalendar. If the
interface reads January 31, 1999 and the user presses the month
increment button, what should it read? If the underlying
implementation uses set(), it might read March 3, 1999. A better
result would be February 28, 1999. Furthermore, if the user presses
the month increment button again, it should read March 31, 1999, not
March 28, 1999. By saving the original date and using either add() or
roll(), depending on whether larger fields should be affected, the
user interface can behave as most users will intuitively expect.
tl;dr
LocalDate.of( 2012 , Month.JANUARY , 31 )
.plusDays( 1 )
2012-02-01
…or…
LocalDate.of( 2012 , 1 , 31 ) // Sane numbering: 1-12 for January-December, and `2012` means year 2012.
.plusDays( 1 )
2012-02-01
java.time
The Calendar class is confusing, awkward, and poorly designed. Among its many problems are these pass-the-units-flag methods. Fortunately, you can now forget all about this class.
The java.time classes built into Java 8 and later now supplant the legacy date-time classes.
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.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
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(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. 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.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Parts
With a LocalDate in hand, you may interrogate for its parts.
To get the day-of-month, that is, the "date" such as 23 from January 23, 2018:
int dayOfMonth = ld.getDayOfMonth() ; // 1-31, depending on length of month.
To get the nth day of the year, from 1-365, or in a leap year, 1-366:
int dayOfYear = ld.getDayOfYear() ;
Math
Adding or subtracting days is quite simple and intuitive in java.time. Convenience methods and span-of-time objects make the code much more clear.
LocalDate dayLater = ld.plusDays( 1 ) ;
So getting tomorrow would be:
LocalDate tomorrow = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ).plusDays( 1 ) ;
Alternatively, you can represent a span-of-time unattached to the timeline. For years-months-days, use Period. For hours-minutes-seconds, use Duration.
Period p = Period.ofDays( 1 ) ;
LocalDate dayLater = ld.plus( p ) ;
Note that java.time uses sane numbering, unlike the legacy classes. The number 2018 is the year 2018. Months are numbered 1-12 for January-December. Days of the week are numbered 1-7 for Monday-Sunday, per the ISO 8601 standard.
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
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, 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.
In addition of date it does not make any difference whether you use DAY_OF_MONTH or DAY_OF_YEAR. However, it makes sense when you get call getter and pass one of those.
Use DATE or DAY_OF_MONTH both are same
Here is the difference :
DATE or DAY_OF_MONTH : Get and Set indicating the day of the month
DAY_OF_WEEK : get and set indicating the week number within the current month
DAY_OF_YEAR : get and set indicating the day number within the current ye
Source : https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html
public static String findDay(int month, int day, int year) {
// Creating a calendar
Calendar calndr = Calendar.getInstance();
calndr.set(Calendar.MONTH, month-1);
calndr.set(Calendar.YEAR, year);
calndr.set(Calendar.DAY_OF_MONTH, day);
String[] strDays = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday" };
return strDays[calndr.get(Calendar.DAY_OF_WEEK)-1].toUpperCase();
}
}

Check if the Calendar date is a sunday

I am trying to figure out how to make my program count the number of Sundays in a week.
I have tried the following thing:
if (date.DAY_OF_WEEK == date.SUNDAY) {
System.out.println("Sunday!");
}
Yet it does not seem to work?
When I try to System.out.Println the date.DAY_OF_WEEK I get: 7
Does anyone know how I can check if the current calendar date is Sunday?
UPDATE FOR MORE INFORMATION
firt of all the date.DAY_OF_WEEK is a Calendar object!
i made sure to set the Calendar object date to a sunday
The system out print where i get 7 is what it returns to me when i try to run date.DAY_OF_MONTH even if the day it set to a sunday
2nd UPDATE TO ALEX
This is more or less my code
Calendar startDate = Calendar.getInstance();
startDate.set(2012, 12, 02);
if (startDate.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
System.out.println("true");
}else {
System.out.println("FALSE");
}
Calendar cal = ...;
if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
System.out.println("Sunday!");
}
Calendar.DAY_OF_WEEK always equals to 7 no matter what instance of Calendar you are using (see this link), it is a constant created to be used with the Calendar.get() method to retrieve the correct value.
It is the call to Calendar.get(Calendar.DAY_OF_WEEK) that will return the real day of week. Besides, you will find useful values in the Calendar class like Calendar.SUNDAY (and the other days and months) in order for you to be more explicit in your code and avoid errors like JANUARY being equal to 0.
Edit
Like I said, the Calendar class does contains useful constants for you to use. There is no month number 12 they start at 0 (see above), so DECEMBER is month number 11 in the Java Date handling.
Calendar startDate = Calendar.getInstance();
startDate.set(2012, Calendar.DECEMBER, 02);
if (startDate.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
System.out.println("true");
} else {
System.out.println("FALSE");
}
Will print true of course.
Note: the Joda-Time project is now in maintenance mode. See this answer if you don't have to work with legacy code.
If you have to work with date or time a lot, you might want to try using Joda-Time.
Your code would look something like this:
LocalDate startDate = new LocalDate(2012, 12, 2);
int day = startDate.dayOfWeek().get(); // gets the day of the week as integer
if (DateTimeConstants.SUNDAY == day) {
System.out.println("It's a Sunday!");
}
You can also get a text string from dayOfWeek():
String dayText = startDate.dayOfWeek().getAsText();
will return the string "Sunday".
tl;dr
boolean todayIsSunday = LocalDate.now( ZoneId.of( "America/Montreal" ) ).getDayOfWeek().equals( DayOfWeek.SUNDAY ) ;
java.time
The other Answers are outdated. The modern approach uses java.time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
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.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument. If critical, confirm the zone with your user.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the code becomes ambiguous to read in that we do not know for certain if you intended to use the default or if you, like so many programmers, were unaware of the issue.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. 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 ) ;
DayOfWeek
For any LocalDate, you can obtain its day-of-week as a DayOfWeek object. The DayOfWeek enum automatically instantiates seven objects, one for each day of the week.
boolean isSunday = ld.getDayOfWeek().equals( DayOfWeek.SUNDAY ) ;
One Sunday per week
count the number of Sundays in a week.
That would be 1, always one Sunday per week.
If your goal is finding the next Sunday, use a TemporalAdjuster defined in TemporalAdjusters class.
TemporalAdjuster ta = TemporalAdjusters.nextOrSame( DayOfWeek.SUNDAY ) ;
LocalDate nextOrSameSunday = ld.with( ta ) ;
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. Hibernate 5 & JPA 2.2 support java.time.
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 brought 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 (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….

Group by date and see if date is today?

I have a few questions about the java Date class, it's really confusing me.
I have two problems:
I have a date object, and I want to see if the date stored in it is later than the begin of the current day or not? So if it's later than today 00:00am or not?
The second problem is, I want to group several date objects by day. But again, I don't understand how I should check if it's within the 24 hours of a specific date.
I think they're kind of related, once I have the 'day' for a date object it can't be to hard?
Any help is really appreciated, the Date class is really confusing me..
The java Date / Calendar classes are really poorly implemented.
Sounds like you should use joda time - specificly LocalDate.
http://joda-time.sourceforge.net/key_partial.html
http://joda-time.sourceforge.net/api-release/org/joda/time/LocalDate.html
This should solve both #1 and #2.
FYI - JodaTime will be replacing the JDK dates eventually (jsr 310)
Rough grouping solution:
public Map<LocalDate, List<Foo>> groupByDate(List<Foo> foos) {
Map<LocalDate, List<Foo>> groupedFoo = new HashMap()<..>
for(Foo foo : foos) {
Date javaDate = foo.getDate();
LocalDate jodaDate = new LocalDate(javaDate);
List<Foo> dateGroupedFoos = groupedFoo.get(jodaDate);
if (null == dateGroupedFoos) {
dateGroupedFoos = new ArrayList()<..>;
groupedFoo.put(jodaDate, dateGroupedFoos);
}
dateGroupedFoos.add(foo);
}
}
I have a date object, and I want to see if the date stored in it is later than the begin of the current day or not? So if it's later than today 00:00am or not?
Create a date for today
Reset hours minutes seconds etc
Use the before method to compare.
The second problem is, I want to group several date objects by day. But again, I don't understand how I should check if it's within the 24 hours of a specific date.
Just group by year, month and date field, or reset the hours, minutes and seconds fields.
Days do not always start at 00:00
So if it's later than today 00:00am or not
Be aware that in some time zones on some dates, the day does not begin at 00:00:00. Anomalies such as Daylight Saving Time (DST) mean the day may start at another time, such as 01:00:00.
Time zone
Determining the start of the day requires a date. Determining a date requires a 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 pseudo-zones such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate today = LocalDate.now( z ) ;
ZonedDateTime
Let java.time determine the first moment of that date. Specify a ZoneId to get a ZonedDateTime object.
ZonedDateTime todayStart = today.atStartOfDay( z ) ; // Determine the first moment of the day in a particular time zone.
Comparison
I want to see if the date stored in it is later than the begin of the current day or not?
Use the comparison methods, isBefore, isAfter, and isEqual.
boolean isFuture = ! ( someZdt.isBefore( todayStart ) ) ; // A shorter way to say "is equal to or later" --> "is NOT before".
Map & Set
I want to group several date objects by day … I don't understand how I should check if it's within the 24 hours of a specific date.
First of all, remember that days are not always 24 hours long. Because of anomalies such as DST, they may be 23 or 25 hours long, or some other length.
So if you want to track them by date, use LocalDate rather than hours. You can interrogate each ZonedDateTime for its LocalDate.
Use a Map, with the date-only portion (LocalDate) as a key, and with the ZonedDateTime objects for that date kept in a Collection such as Set for the map entry’s value.
Map < LocalDate, Set < ZonedDateTime > > map = new HashMap <>( );
Here's a full snippet of example code. You can run this code live at IdeOne.com.
Map < LocalDate, Set < ZonedDateTime > > map = new HashMap <>( );
Set < ZonedDateTime > set = null;
ZoneId z = ZoneId.of( "Africa/Tunis" );
LocalDate today = LocalDate.now( z );
ZonedDateTime todayStart = today.atStartOfDay( z ); // Determine the first moment of the day in a particular time zone.
map.putIfAbsent( todayStart.toLocalDate( ) , new HashSet <>( ) );
set = map.get( todayStart.toLocalDate( ) ) ;
set.add( todayStart );
ZonedDateTime zdt1 = todayStart.plusHours( 6 );
map.putIfAbsent( zdt1.toLocalDate( ) , new HashSet <>( ) );
set = map.get( zdt1.toLocalDate( ) ) ;
set.add( zdt1 );
ZonedDateTime zdt2 = todayStart.plusDays( 2 );
map.putIfAbsent( zdt2.toLocalDate( ) , new HashSet <>( ) );
set = map.get( zdt2.toLocalDate( ) ) ;
set.add( zdt2 );
ZonedDateTime zdt3 = todayStart.plusMonths( 4 );
map.putIfAbsent( zdt3.toLocalDate( ) , new HashSet <>( ) );
set = map.get( zdt3.toLocalDate( ) ) ;
set.add( zdt3 );
System.out.println( "map.toString(): " + map );
We expect to see 3 entries in the map, with one of those values being a set of two items while the other two values are a set of one item each. Read this output carefully, as a HashSet does not return items by the order in which they were put.
map.toString(): {2018-01-25=[2018-01-25T00:00+01:00[Africa/Tunis]], 2018-01-23=[2018-01-23T00:00+01:00[Africa/Tunis], 2018-01-23T06:00+01:00[Africa/Tunis]], 2018-05-23=[2018-05-23T00:00+01:00[Africa/Tunis]]}
Let's break that apart for clarity. We see that January 23 has a pair of values in its set, while January 25 and May 23 both have a single.
2018-01-25=[2018-01-25T00:00+01:00[Africa/Tunis]]
2018-01-23=[2018-01-23T00:00+01:00[Africa/Tunis], 2018-01-23T06:00+01:00[Africa/Tunis]],
2018-05-23=[2018-05-23T00:00+01:00[Africa/Tunis]]
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
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

Categories