Get nearest DateTime by specifying hour in Joda Time [duplicate] - java

I'd like to be able to get a correct DateTime for the NEXT occurrence of a time that I can specify with just an hour and minute. I'd also like to be able to do this by specifying the same thing for that hour and minute, but for the next occurrence of that on (say) a Wednesday.
Also, note that if the current minute has already "started" (which I guess means that we're in 00 milliseconds of that minute) then, again, we need to find the "next" occurrence of that time.
An example with (say) getting a DateTime for the next 10:34 AM and next 12:45 PM that's on a Wednesday, would be greatly appreciated.
How can I do this in Joda?

Something like this, for "next 10:34 AM on a Wednesday:"
DateTime getNextTimeOnDay(int dayOfWeek, int hourOfDay, int minuteOfHour)
{
DateTime now = new DateTime();
DateTime then = now
.withDayOfWeek(dayOfWeek)
.withHourOfDay(hourOfDay)
.withMinuteOfHour(minuteOfHour)
.withSecondOfMinute(0)
.withMillisOfSecond(0);
return then.isBefore(now) ? then.plusWeeks(1) : then;
}
DateTime nextWednesdayAtTenThirtyFour
= getNextTimeOnDay(DateTimeConstants.WEDNESDAY, 10, 34);
// as of now, this is 2012-01-06T10:34:00.000-05:00

java.time
The Answer by Matt Ball is correct for Joda-Time. The makers of Joda-Time have said we should move to the java.time framework built into Java 8 and later as soon as is convenient. So here is the same kind of code rewritten for java.time.
DayOfWeek enum
Since java.time is built into Java, it seems reasonable to replace the argument using an int as the day-of-week with the bundled enum DayOfWeek.
Time Zone
The code in the other Answer has one major issue: It depends implicitly on the JVM’s current default time zone. That default can change at any moment, even during runtime(!). Better to always specify the expected/desired time zone. So I added another argument to our method.
DST Adjustment
If your specified hour and minute land in an anomaly such as Daylight Saving Time (DST), java.time will make an adjustment. Be sure to read the doc to understand that behavior and verify it meets with your desires/expectations.
Using a TemporalAdjustor of next( dayOfWeek ) defined in TemporalAdjustors (notice the plural s) means we will get the next such day, going forward in the future and never the past. So we can drop the ternary test in the return statement.
public ZonedDateTime getNextTimeOnDay ( ZoneId zoneId, DayOfWeek dayOfWeek, int hourOfDay, int minuteOfHour ) {
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime then = now
.with ( TemporalAdjusters.next ( dayOfWeek ) )
.withHour ( hourOfDay )
.withMinute ( minuteOfHour )
.withSecond ( 0 )
.withNano ( 0 );
return then;
}
An example calling that method.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime nextWednesdayAtTenThirtyFour = this.getNextTimeOnDay ( zoneId, DayOfWeek.WEDNESDAY, 10, 34 );
Dump to console.
System.out.println ( nextWednesdayAtTenThirtyFour );
2016-01-20T10:34-05:00[America/Montreal]
By the way, you may want to pass a ZonedDateTime to be used by the method as the starting point rather than assume “now”. This route might be more useful/flexible and facilitate testing. If you choose this route, no need to pass the ZoneId as the passed ZonedDateTime carries with it the assigned time zone.

Related

Getting the startime and endtime of the day in epochmillis for different timezones - java

I am trying to get the start time (00:00:00) and the end time (23:59:59) of a day in the PST time zone. I have tried the following code, but for some reason, I am only getting the start and end times in UTC. I have tried changing the timezone to include "America/Los_angeles", but the output timestamp is always showing start and end times for GMT/UTC.
My code:
val time_zone = ZoneId.of("America/Los_Angeles")
val today_date = LocalDate.now(time_zone).plusDays(0)
val start_time = today_date + " " + "00:00:00"
val end_time = today_date + " " + "23:59:59"
val date_format = new SimpleDateFormat("yyyy-MM-dd");
val start_millis = date_format.parse(start_time).getTime();
val end_millis = date_format.parse(end_time).getTime();
start_millis
Output:
res375: Long = 1656460799000
In the epoch converter, 1656460799000 gives me this:
Anything I am missing here? Should I update any package, etc.?
java.time
The modern approach uses the java.time classes only.
No need to ever use SimpleDateFormat, Date, Calendar, and the other terrible legacy date-time classes. If need be, you can convert to and fro via new conversion methods added to the old classes.
Start of day
I am trying to get the start time (00:00:00)
Do not assume the day starts at 00:00. Some dates in some zones start at another time such as 01:00. Let java.time determine the first moment of the day using LocalDate#atStartOfDay.
End of day
the end time (23:59:59) of a day
You would be missing an entire last second of the day with that approach.
Date-time work is commonly done with the Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive. So a day starts with the first moment of the day, and runs up to, but does not include, the first moment of the following day. Half-Open approach neatly contains that full last second of the day.
Time zones
PST time zone.
There is no such thing as a time zone named PST. Such 2-4 letter pseudo-zones are used by the popular media to indicate a hint about the time zone. But these pseudo-zones are not standardized, and are not even unique! Use only for localized presentation to humans, never for data storage or data exchange.
Real time zones are named with Continent/Region.
Perhaps by “PST” you meant “Pacific Standard Time”, which often indicates America/Tijuana, or America/Los_Angeles or America/Vancouver or others.
Or perhaps by “PST” you meant “Philippines Standard Time” covering the Asia/Manila time zone.
Example code
Capture the current moment as seen in a time zone.
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
Extract the date.
LocalDate today = zdt.toLocalDate() ;
Determine the first moment of the day.
ZonedDateTime zdtStartOfDay = today.atStartOfDay( z ) ;
And determine the first moment of the following day.
ZonedDateTime zdtStartOfFollowingDay = today.plusDays( 1 ).atStartOfDay( z ) ;
You may want to see the length of time. Not all days are 24 hours.
Duration d = Duration.between( zdtStartOfDay , zdtStartOfFollowingDay ) ;
Adjust both moments to UTC by extracting an Instant object. That class represents a moment as seen in UTC.
Instant start = zdtStartOfDay.toInstant() ;
Instant end = zdtStartOfFollowingDay.toInstant() ;
For each, get the count of milliseconds since the epoch reference of first moment of 1970 as seen in UTC, 1970-01-01T00:00Z.
long startMilli = start.toEpochMilli() ;
long endMilli = end.toEpochMilli() ;
However, I strongly recommend against tracking time as a count of milliseconds. This approach is confusing, as at least a couple dozen epoch reference points are commonly used. And a long cannot be interpreted by a human reader, so mistakes may go unnoticed.
Instead, data storage and data exchange should generally be done as text using the standard ISO 8601 formats. The java.time classes use these standard formats by default when parsing/generating text.
String startText = start.toString() ;
String endText = end.toString() ;
ThreeTen-Extra
You may want to add the ThreeTen-Extra library to your project. This gives you access to the Interval class, to represent a span of time as a pair of Instant objects.
Interval allDayLongToday = org.threeten.extra.Interval.of( start , end ) ;
This class provides several helpful methods. These include contains, encloses, abuts, union, intersection, and more.
Instant invoiceRecorded = … some `Instant` ;
boolean invoiceRecordedToday = allDayLongToday.contains( invoiceRecorded ) ;
Just add this section to your code:
date_format.setTimeZone(TimeZone.getTimeZone("PST"));
Then it will work as you want :)

Java code to check if event timestamp falls in weekdays and business hours from 9:30 AM to 4:00 PM

What is the best way in Java to check if event timestamp falls in weekdays and business hours from 9:30 AM to 4:00 PM and name the variable like Event_Type = "business" or "non business" based on the comparison.
1) Time stamps are Unix Time stamps.
2) Time zone differences are not a concern as all event time stamps abelong to the same timezone (Chicago Central TimeZone).
3) Monday, Tuesday, Wednesday, Thursday and Friday are business days. Remaining days are not. Within in these business days if timestamp falls between 9:30 AM to 4:00 PM then event_type varible is equal to "business" other wise it should be non business.
I am looking for the best way to do this efficiently for a large amount of data.
I am looking for something using java.util Calendar Object
Unix Time
The phrase "Unix Time" does not have an exact meaning. Often people mean a count of seconds since the first moment of 1970 in UTC, ignoring Leap second. Sometimes people mean another granularity, commonly milliseconds. In the old days a 32-bit integer was used, creating the Year 2038 Problem, nowadays often a 64-bit integer is used.
Time zone
Time zone differences are not a concern as all event time stamps abelong to the same timezone (Chicago Central TimeZone).
Time zone is always a concern! To determine a day-of-week we need a date. To determine a date we need a time zone. For any given moment the date (and time-of-day) varies around the world by time zone. For example, a few minutes after midnight in Paris is a new day but is still “yesterday” in Montréal.
Furthermore, the Unix-style timestamps you mentioned are commonly intended to represent a moment in UTC. So you need a time zone to adjust into Chicago time frame.
If you do not specify a time zone, the JVM’s current default time zone is implicitly silently applied. That means your results will vary as that default time zone varies. Changes to the host computer and OS may impact the default time zone, as can any code in any app within the JVM via a call to TimeZone.setDefault – even during runtime of your code. So never rely on the implicit default; always specify your desired/expected time zone.
CST and Chicago Central Time and Central Time Zone are not exactly time zones. True time zones are named with a continent/region pattern. These time zones contain a set of rules for handling anomalies such as Daylight Saving Time (DST) that can vary historically for the various regions.
java.time
The Question and the accepted Answer both use troublesome old date-time classes bundled with the earliest versions of Java. Those classes are now legacy, now supplanted by the java.time framework built into Java 8 and later.
Get zoned date-time
First step, convert your count-of-seconds-from-epoch to an Instant, a moment on the timeline in UTC with a resolution of nanoseconds.
long secondsSinceEpoch = 1464645007L;
Instant instant = Instant.ofEpochSecond ( secondsSinceEpoch );
Apply a time zone (ZoneId) to get an object with the Chicago wall-clock time and with the Chicago-area’s history of anomaly adjustments (ZonedDateTime).
ZoneId zoneId = ZoneId.of( "America/Chicago" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Predicate
Now we can move to the core of the question, asking if this particular moment happens to be land on a week-day and within business hours within the context of the Chicago-area time zone.
Java 8 and later includes a formal structure for asking a boolean question, for asking if an object meets some criteria: Predicate. This simple interface has a method test which we need to implement, where we define our criteria for a TRUE or a FALSE.
Below is the source code for an entire class implementing the Predicate interface with a test method that holds our business logic for testing day-of-week and time-of-day.
First using Java Generics, we declare that we are working with an object of ZonedDateTime.
Then we use the handy DayOfWeek enum to define what we mean by "week-day". An EnumSet is a handy way to collect a subset of the values defined in an enum, as where where we collect 5 of the 7 possible day-of-week values.
We define business hours as LocalTime values. Be careful about the Local… types as they purposely have no time zone info. But here in this code the use of LocalTime is fine, as we extract the local time from the ZonedDateTime within the context of a time zone we expect.
The approach of this class assumes we have a ZonedDateTime assigned a Chicago time zone. For defensive programming, we should verify that assumption. If we were passed an object for Pacific/Auckland time zone assigned, the rest of our code would be testing the day-of-week and time-of-day for New Zealand, which is certainly not the same time frame as Chicago. As a simple solution, we test the passed ZonedDateTime for a ZoneId whose name is America/Chicago. A more sophisticated alternative might be to require passing an Instant, or a superclass, and convert the passed data into a ZonedDateTime with Chicago ZoneId. That is left as an exercise to the reader.
Another alternate design you could pursue is to pass 4 arguments to a constructor rather than hard-code the definition of weekdays, start time, stop time, and time zone as we do here in four private static final objects.
The rest of the code is straightforward if() testing. The start and stop times are compared using the Half-Open approach commonly used with date-time work. The beginning is inclusive while the ending is exclusive. You use this Half-Open approach intuitively when you say “Lunch break is noon to 1 PM”.
We also add a toString method to verify the class’s definitions of week-day, business hours, and time zone.
package com.example.javatimestuff;
import java.time.DayOfWeek;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.EnumSet;
import java.util.function.Predicate;
/**
*
* © 2016 Basil Bourque. This source code may be used at your own risk according
* to the terms of the ISC License: https://opensource.org/licenses/ISC
*
* #author Basil Bourque.
*/
public class isDuringBusinessHoursPredicate implements Predicate<ZonedDateTime> {
private static final EnumSet<DayOfWeek> WEEKDAYS = EnumSet.of ( DayOfWeek.MONDAY , DayOfWeek.TUESDAY , DayOfWeek.WEDNESDAY , DayOfWeek.THURSDAY , DayOfWeek.FRIDAY );
private static final LocalTime START = LocalTime.of ( 9 , 30 );
private static final LocalTime STOP = LocalTime.of ( 16 , 0 );
private static final ZoneId ZONEID_AMERICA_CHICAGO = ZoneId.of ( "America/Chicago" );
// Method tests to see if the passed date-time is on a Chicago week-day and within business hours.
#Override
public boolean test ( ZonedDateTime zdt ) {
// Verify argument.
boolean expectedTimeZone = zdt.getZone ().equals ( ZONEID_AMERICA_CHICAGO );
if ( ! expectedTimeZone ) {
throw new IllegalArgumentException ( "Expected argument to have a time zone: " + ZONEID_AMERICA_CHICAGO );
}
// Determine the day-of-week to see if it with our definition of a week-day.
DayOfWeek dayOfWeek = zdt.getDayOfWeek ();
boolean isWeekday = WEEKDAYS.contains ( dayOfWeek );
// If a week-day, determine if the time-of-day is within our definition of business hours. Half-open approach where the beginning is *inclusive* while the ending is *exclusive*.
if ( isWeekday ) {
LocalTime localTime = zdt.toLocalTime ();
boolean withinBusinessHours = ( ! localTime.isBefore ( START ) && localTime.isBefore ( STOP ) );
return withinBusinessHours;
} else {
return false;
}
}
#Override
public String toString () {
return "isDuringBusinessHours{ " + "weekdays=" + WEEKDAYS.toString () + " | start=" + START + " | stop=" + STOP + " | timeZone: " + ZONEID_AMERICA_CHICAGO + " }";
}
}
Now back to our code we began at the top of this Answer, to use an instance of our new isDuringBusinessHoursPredicate class.
Predicate p = new isDuringBusinessHoursPredicate ();
boolean isBiz = p.test ( zdt );
Dump to console.
System.out.println ( "zdt: " + zdt + " | isBizTime: " + isBiz + " | p: " + p );
zdt: 2016-05-30T16:50:07-05:00[America/Chicago] | isBizTime: false | p: isDuringBusinessHours{ weekdays=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY] | start=09:30 | stop=16:00 | timeZone: America/Chicago }
Why Predicate?
Why bother to move our criteria logic into a class implementing Predicate? If you ever need that logic in more than one place, you now have a simple way to re-use that logic. Also, that interface happens to be a functional interface (an interface requiring only a single method) which can then be used with Java Streams (see this and this) and Lambda expressions for some very powerful code with very short (simple?) syntax.
Here's an option
Calendar d = Calendar.getInstance();
Calendar begin = Calendar.getInstance();
Calendar end = Calendar.getInstance();
begin.set(Calendar.HOUR, 9);
begin.set(Calendar.MINUTE, 29);
begin.set(Calendar.AM_PM, Calendar.AM);
end.set(Calendar.HOUR, 4);
end.set(Calendar.MINUTE, 01);
end.set(Calendar.AM_PM, Calendar.PM);
if (d.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY || d.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY
|| (d.after(begin) && d.before(end))) {
System.out.println("YAY!");
}
Here is precisely the solution you need and no BS.
ZonedDateTime localDateTime = ZonedDateTime.now();
ZonedDateTime nowInNewYork= ZonedDateTime.now(ZoneId.of("America/New_York"));
DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
if(dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY){
System.out.println("NOT Within Working Hours);
} else if(nowInNewYork.getHour() < 9
|| (nowInNewYork.getHour() == 9 && nowInNewYork.getMinute() <30)
|| (nowInNewYork.getHour() > 15)){
System.out.println("NOT Within Working Hours);
} else {
System.out.println("Within Working Hours);
}

Printing Time and Date in both Universal Time and Standard Time

Writing a Java application that takes user input into a Time and Date class, but I am not sure how to take this user input and convert it into Universal and Standard time... I have spent multiple hours surfing the web and stack overflow and have not been able to find a solution.
I have hours, minutes, seconds, year, month, day all in separate integer variables and need to display them in Universal and Standard time.
Thanks for taking a look...
There are two solutions:
first is place all of input in the string and parse it:
String dateStr = ""
//put your input in this string in some format/ example:
//dateSttr = year + "." + month + "." + day + " " + hour + ":" + minute;
//It is better to use StringBuilder
DateFormat inputFormat = new SimpleDateFormat("yyyy.MM.dd hh:mm");
//note that hh is 12h-format and HH is 24h-format
DateFormat outputFormat1 = new SimpleDateFormat("your_outputFormat");
DateFormat outputFormat2 = new SimpleDateFormat("your_another_outputFormat");
Date date = inputFormat.parse(dateStr);
String o1, o2;
o1 = outputFormat1.format(date);
o2 = outputFormat2.format(date);
//o1 and o2 is your result.
For the rules, how this formats is done, see javadoc
The second solution is to get a new date and set your parameters:
Calendar cln = Calendar.getInstance().clear();
//by default you get a calendar with current system time
//now set the fields. for example, day:
cln.set(Calendar.YEAR, 2015);
cln.set(Calendar.MONTH, Calendar.FEBRUARY);
cln.set(Calendar.DAY_OF_MONTH, 17);
cln.set(Calendar.HOUR_OF_DAY, 18);//Calendar.HOUR for 12h-format
cln.set(Calendar.MINUTE, 27);
See more about setting calendar in javadoc
Note, that in the second variant, you might have some fields undefiend.
If #JonSkeet 's assumption and mine is correct, you're starting with either UTC or your local time. Displaying it is just a matter of formatting your output.
For the other type of time, you add or subtract a number of hours, which you can find on the web. The tricky part is that this may push you into the next calendar day, or pull you back into the previous one. To deal with that, I figure you want to either
implement an adder for year, month, day, hour--or
convert those to decimal somethings (Excel uses days, for instance, where as I write this it's 42328.08813), shift the value by the appropriate number of hours, and convert it back.
java.time
The Answer by TEXHIK is correct, but outdated. Also, as others mentioned, I do not know what you mean by "Universal and Standard time". But I'll try to get you part way there.
As of Java 8, the old java.util.Date/.Calendar classes have been supplanted by the new java.time framework. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
The ZonedDateTime class has a factory method taking numbers for year, month, and so on.
Plus you must specify a time zone. If your numbers represent a date-time in UTC, use the ZoneOffset.UTC constant. For other time zones, specify a ZoneId object by using a proper time zone name; never use the 3-4 letter codes such as EST or IST as their are neither standardized nor unique.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
// ZoneId zoneId = ZoneOffset.UTC; // ZoneOffset is a subclass of ZoneId.
ZonedDateTime zdt = ZonedDateTime.of( 2015 , 1 , 2 , 3 , 4 , 5 , 6 , zoneId );
zdt: 2015-01-02T03:04:05.000000006-05:00[America/Montreal]
You can convert to UTC or another time zone.
ZonedDateTime zdt_Kolkata = zdt.withZoneSameInstant ( ZoneId.of("Asia/Kolkata") );
ZonedDateTime zdt_Utc = zdt.withZoneSameInstant ( ZoneOffset.UTC );
zdt_Kolkata: 2015-01-02T13:34:05.000000006+05:30[Asia/Kolkata]
zdt_Utc: 2015-01-02T08:04:05.000000006Z
If working with classes not yet updated for java.time, convert to a java.util.Date. First extract a Instant object, a moment on the timeline always in UTC.
java.util.Date date = java.util.Date.from ( zdt.toInstant () );

create/find java class with simple constructor (hour, min) for use extending GregorianCalendar

I want to store a user-specified rough time of day (unspecified date) in a Java object. Can I instantiate a LocalTime object and set its hours and minutes in one line of Java code? Or is there a different, more suitable existing class?
I have insufficient google wizardry to find such. Elaboration follows, and thank you:
< 1 year android/java exp.
I'm extending the GregorianCalendar class and coding a constructor for FutureCal that takes integer hour (0-23) and minute and returns a calendar-ish object with date/time matching the first future occurrence of that hour:minute (will be either today or tomorrow--for notification/reminder stuff). To allow for other constructors that might have two integers, I would like to use or create a TimeOfDay class/type (comprised of integers hour & minute) and use that instead as parameter to my constructor. Is this a) possible b) appropriate?
Thanks for your time.
Joda-Time
The Joda-Time library is a popular and well-worn replacement for the awful mess that is GregorianCalendar, java.util.Date, SimpleTextFormat, and such. Joda-Time works on Android.
LocalTime
Joda-Time offers a LocalTime to represent a time-only value without any date or time zone. This class has the constructor you want, passing hour and minute values.
java.time
The new java.time package built into Java 8 (inspired by Joda-Time) also offers a similar LocalTime class. But Java 8 technology is not available for Android.
Example Code
Here is some example code using Joda-Time 2.4.
LocalTime localTime = new LocalTime( 13, 15 ); // Quarter-hour after 1 PM.
You can apply that LocalTime to a DateTime object. So, Joda-Time already provides everything you are trying to invent. Here is some example code setting today’s date-time to the desired time-of-day unless that has already passed in which case we slide to tomorrow’s date and re-apply our desired time-of-day.
LocalTime localTime = new LocalTime( 13 , 15 ); // Quarter-hour after 1 PM.
System.out.println( "localTime: " + localTime );
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" ); // Or DateTimeZone.UTC
DateTime today = localTime.toDateTimeToday( timeZone );
DateTime now = DateTime.now(); // You may want to pad an bit of extra time in case now is extremely close to midnight (new day).
if ( today.isBefore( now ) ) {
// If the local time in question when applied to today has already past, then
// adjust to tomorrow while accounting for Daylight Saving Time or other anomaly.
DateTime tomorrowInitial = today.plusDays( 1 ); // Get tomorrow by adding 1 day to today.
DateTime tomorrow = localTime.toDateTime( tomorrowInitial ); // DST or other anomaly may mean that tomorrow got adjusted to a different time-of-day. Override with our desired time-of-day.
System.out.println( "tomorrow: " + tomorrow );
// return tomorrow;
}
System.out.println( "today: " + today );
// return today;
When run.
localTime: 13:15:00.000
tomorrow: 2014-10-09T13:15:00.000-04:00
today: 2014-10-08T13:15:00.000-04:00
Best to avoid java.util.Date. But if required, you may convert from Joda-Time.
java.util.Date date = today.toDate(); // Convert from Joda-Time DateTime to java.util.Date.
Maybe I didn't understood all but why not use a Calendar? I mean, you can set the time in a Calendar object.
int hour = 'your hour';
int minute = 'your minute';
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR, hour).
cal.set(Calendar.MINUTE, minute);
Can I instantiate a LocalTime object and set its hours and minutes in
one line of Java code?
Yes, provided that you are using Java 8 (LocalTime seems new in Java 8):
LocalTime time = LocalTime.of(hour, minute);
When you are wondering about the behavior of specific classes, it would behoove you to consult their documentation, in this case, http://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html. In most cases, you will get your answer faster, plus answers to followup questions.

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