In android, while running the below code snippet, date3 returns -1
booking_year2 = 2038;
booking_month2 = 1;
booking_day2 = 17;
Time t = new Time();
t.set(booking_day2, booking_month2 - 1, booking_year2);
long date3 = t.toMillis(false);
//date3 returns 2147451300000 as expected
//But if we run with values:
booking_year2 = 2038;
booking_month2 = 1;
booking_day2 = 18;
//date3 returns -1
While, the Time object 't' have expected value in all conditions, the long value returned by toMillis() function is only -1.
And also, for all the upper values of date after jan 19, 2038, the toMillis() function returns only -1 and not the expected value.
I didn't understood and didn't found any suitable reason or solution for this.
Please let me know, if I am doing anything wrong or is there any other way to find the millisecond values after this date.
That is the year-2038-problem which affects the class android.text.format.Time (android class). The problem is typical for UNIX. And the documentation of the class says:
"It is modelled after struct tm, and in fact, uses struct tm to implement most of the functionality."
So it uses in the background a C++-solution which is also widespread on UNIX-systems. This datatype has only 32 bits, so in year 2038 integer overflow will happen. Finally you can hope on a future bugfix, see following bug report of Android:
Issue 37653: android.text.format.Time not year 2038 safe
A workaround is to use Joda-Time, the open-source third-party library.
DateTime dateTime = new DateTime( 2099, 1, 2, 3, 4, 5, DateTimeZone.UTC );
long millis = dateTime.getMillis();
Dump to console…
System.out.println( "dateTime: " + dateTime );
System.out.println( "millis: " + millis );
When run…
dateTime: 2099-01-02T03:04:05.000Z
millis: 4071006245000
Related
I have many timestamps (start, end) which define an interval and want to efficiently check if they overlap another single interval. If yes, compute overlap duration, otherwise return 0.
interval: 18:00 same day until 08:00 the next day.
start | end
2018-01-02 14:59:18.922|2018-01-02 14:59:38.804
2018-01-02 18:32:59.348|2018-01-02 20:30:41.192
2018-01-02 01:54:59.363|2018-01-02 01:54:59.363
2018-01-03 00:10:38.831|2018-01-03 00:11:53.103
I am unsure how to efficiently define the next day efficiently.
edit
LocalDate
has a method toInterval().overlaps(anotherInterval). I simply am unsure how to get fitting interval (18:00 - 08:00 next day) in a generic way, i.e. without manually reading the YYYMMDD and then creating a new object.
a bit similar is Find if hours ranges overlap regardless of the date
edit 2
toInterval is only present for jodatime - not java.time / JSR-310. What would be a viable way to calculate overlap duration with java.time?
edit3
A solution with jodaTime:
val begin = new DateTime(new java.sql.Timestamp().getTime())
val stop = new DateTime(new java.sql.Timestamp().getTime())
val i1 = new Interval(begin, stop)
val start = new DateTime(begin.year.get , begin.monthOfYear.get, begin.dayOfMonth.get, startHour, 0, 0, 0);
val endIntermediate =stop.toDateTime.plusDays(1)
val end = new DateTime(endIntermediate.year.get , endIntermediate.monthOfYear.get, endIntermediate.dayOfMonth.get, endHour, 0, 0, 0);
val i2 = new Interval(start, end)
val overlap = i1.overlap(i2)
val overlapDurationOrNull = overlap.toDuration
seems to work, but still is clumsy.
I believe that the following method gives you the equivalent of your Joda-Time solution.
private static final LocalTime START = LocalTime.of(18, 0);
private static final LocalTime END = LocalTime.of(8, 0);
public static Duration overlap(ZonedDateTime currentStart, ZonedDateTime currentEnd) {
ZonedDateTime singleIntervalStart = currentStart.with(START);
ZonedDateTime singleIntervalEnd = currentStart.plusDays(1).with(END);
if (currentEnd.isBefore(singleIntervalStart)) {
// no overlap
return Duration.ZERO;
}
ZonedDateTime overlapStart = currentStart.isBefore(singleIntervalStart)
? singleIntervalStart : currentStart;
ZonedDateTime overlapEnd = currentEnd.isBefore(singleIntervalEnd)
? currentEnd : singleIntervalEnd;
return Duration.between(overlapStart, overlapEnd);
}
For trying it out with the timestamps from your question I am using the following utility method:
private static void demo(String from, String to) {
ZoneId zone = ZoneId.of("Atlantic/Stanley");
Duration overlapDuration = overlap(LocalDateTime.parse(from).atZone(zone),
LocalDateTime.parse(to).atZone(zone));
System.out.println("" + from + " - " + to + ": " + overlapDuration);
}
Now I call it like this:
demo("2018-01-02T14:59:18.922", "2018-01-02T14:59:38.804");
demo("2018-01-02T18:32:59.348", "2018-01-02T20:30:41.192");
demo("2018-01-02T01:54:59.363", "2018-01-02T01:54:59.363");
demo("2018-01-03T00:10:38.831", "2018-01-03T00:11:53.103");
And the output is:
2018-01-02T14:59:18.922 - 2018-01-02T14:59:38.804: PT0S
2018-01-02T18:32:59.348 - 2018-01-02T20:30:41.192: PT1H57M41.844S
2018-01-02T01:54:59.363 - 2018-01-02T01:54:59.363: PT0S
2018-01-03T00:10:38.831 - 2018-01-03T00:11:53.103: PT0S
In the first example 14:59 is before 18:00, so the result is an overlap of 0. In the second example the whole interval is counted as overlap (nearly 2 hours). Note that in the last two examples no overlap is reported because the the times are many hours before 18:00. I am unsure whether this is what you wanted since the times are also before 08:00.
You can simply use LocalDate.plusDays to add a day.
Assuming an iteration where the following are to be compared:
LocalDateTime d1 = LocalDateTime.parse("2018-01-02T14:59:18"),
d2 = LocalDateTime.parse("2018-01-02T14:59:38");
You can create the 18:00 and 08:00 date/time objects using:
LocalDateTime start = LocalDateTime.of(d1.toLocalDate(), LocalTime.of(18, 0));
LocalDateTime end = LocalDateTime.of(d1.toLocalDate().plusDays(1),
LocalTime.of(8, 0));
I've assumed that 18:00 is on the same day as d1.
I am trying to write a method which takes two java.util.Date's as parameters and returns a random java.util.Date between these two in Scala. However, I get the same dummy result each time. What is wrong with my code?
Note:
randomDateBetween(new Date(2017, 1, 1), new Date(2018, 1, 1)) returns Tue Jun 12 09:36:00 EET 3917 like all the time
Code:
def randomDateBetween( firstDate : Date, secondDate : Date) : Date =
{
val ratio = new Random().nextInt(100);
val difference = (secondDate.getTime - firstDate.getTime)
val surplusMillis = (difference * (ratio / 100.0)).asInstanceOf[Long]
val cal = Calendar.getInstance()
cal.setTimeInMillis(surplusMillis + firstDate.getTime)
return cal.getTime()
}
I fixed it guys, thank you anyway. Cause of the error was java.util.Date being deprecated. I changed my method call like this and it worked perfectly fine:
val date1 = Calendar.getInstance
val date2 = Calendar.getInstance
date1.set(2017, 1, 1)
date2.set(2018, 1, 1)
randomDateBetween(date1.getTime, date2.getTime)
You need to seed the Random object like so:
Random.setSeed(System.currentTimeMillis())
val ratio = new Random().nextInt(100)
(Java syntax here, rather than Scala)
ThreadLocalRandom
The Answer by sheunis is correct but outdated.
Another outdated option is Math.random.
randomNum = minimum + ( int )( Math.random() * maximum );
The modern approach since Java 7 is ThreadLocalRandom. See this Answer.
long random = ThreadLocalRandom.current().nextLong( minimum , maximum + 1 );
Both of these alternatives to Random are initialized with an internally generated seed that may not otherwise be modified.
Avoid legacy date-time classes.
Also you are using troublesome old date-time classes Date and Calendar that are now legacy, supplanted by java.time classes.
Using java.time
For date-only values without time-of-day and without time zone, use LocalDate class.
LocalDate start = LocalDate.of( 2017 , Month.JANUARY , 1 ) ;
LocalDate stop = LocalDate.of( 2018 , Month.JANUARY , 1 ) ;
Count days between, to determine random number of days.
long maxDays = ChronoUnit.DAYS.between( start , stop ) ;
So we want to add a random number of days, as little as zero and as much as maxDays.
long days = ThreadLocalRandom.current().nextLong( 0 , maxDays + 1 );
LocalDate ld = start.plusDays( days ) ;
Date randomDate= new Date(ThreadLocalRandom.current().nextLong(fromDate.getTime(), toDate.getTime()+1));
I don't know much about scala. I have tested it in java, I think this solution is applicable for scala as well. Please modify the code if needed.
In Java I have the following test that passes fine
// 42 bits of time is good enough for the next 100 years.
// An IEEE double has 52 bits of mantissa, so our dates can be easily fit.
#Test
public void testMaxBits() throws ParseException {
// Maximum 42 bit integer
long millis = (1L << 42) - 1;
Date date = new Date(millis);
//DateTime maxDate = new DateTime(2109, 5, 15, 8, 35, 11, 103);
Date maxDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").parse("2109-05-15T08:35:11.103");
Assert.assertEquals(maxDate, date);
}
Now, I want to do the same sort of thing in C#, so I have a test in LinqPAD that test the C# implementation for correctness
DateTime maxDate = new DateTime(2109, 5, 15, 8, 35, 11, 103);
long beginTicks = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
long l = (1L << 42) - 1;
DateTime date = new DateTime(beginTicks + l, DateTimeKind.Utc);
maxDate.Dump();
date.Dump();
The output don't match, the values outputted ToString() values are
maxDate = 15/05/2109 08:35:11
date = 06/01/1970 02:10:04
What am I missing here?
Edit. I have see a great answer below from #zmitrok, I have changed
DateTime date = new DateTime(beginTicks + l, DateTimeKind.Utc);
to
DateTime date = new DateTime(beginTicks +
l * TimeSpan.TicksPerMillisecond, DateTimeKind.Utc);
but now get
date = 15/05/2109 07:35:11
Where has the hour gone?
Your test is basically confusing ticks with milliseconds. If you only need to store a number of milliseconds since the unix epoch, then do so - but I'd recommend using something like this to perform the conversion:
public static readonly DateTime UnixEpoch
= new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public DateTime FromMillisecondsSinceUnixEpoch(long milliseconds)
{
return UnixEpoch.AddMilliseconds(milliseconds);
}
(As a side-note, that method already exists in my Noda Time project... hint hint :)
Your test would then be:
[TestMethod]
public void TestMaxBits()
{
long maxMillis = (1L << 42) - 1;
DateTime maxDate = DateTimeHelper.FromMillisecondsSinceUnixEpoch(maxMillis);
Assert.Greater(maxDate, new DateTime(2100, 1, 1, 0, 0, 0));
}
Note that:
This code doesn't mention ticks at all, because you're not interested in ticks
This code doesn't assert that the maximum date is some very specific value, because that's not what you care about; you care that 42 bits of time will carry you until the end of the century. (The "next 100 years" comment is somewhat specious, as 2109 is less than 100 years away from now, so I'll assume it really means "until the end of the 21st century.")
That of course make your question of "Where has the hour gone?" irrelevant - but the answer to that is simply that SimpleDateFormat defaults to using the system time zone, so you're actually relying on the time zone of the system you're running the test on, which is a really bad idea. If you set the time zone of the SimpleDateFormat to UTC, you'll find that it's 07:35:11 in Java as well.
The constructor you are using takes ticks as the first argument, however you are passing a value that was added to milliseconds.
Ticks: A date and time expressed in the number of 100-nanosecond intervals that have elapsed since January 1, 0001 at 00:00:00.000 in the Gregorian calendar.
I think you need to multiply ticks by this constant: https://msdn.microsoft.com/en-us/library/system.timespan.tickspermillisecond%28v=vs.110%29.aspx
My input is a beginning date and an end date. And I want to check that it is between December 1 and March 31. (The year can change, and there will be only dates in, or dates outside this period).
So far I didn't found any solution with Joda-time. Can somebody give me a starting point how to do(not code, just the logic)?
I didn't checked the code yet, but it is VERY Ugly, and I want to find an algorithmic solution
public static boolean isInWinter(Contract contract) {
logger.info("begin isInWinter:");
DateTime beginDate = contract.getBeginningDate();
DateTime endDate = contract.getEndDate();
/*
* If the year is different (etc 2012 dec,2013 marc) check that the
* beginning month is december, and the end month is jan,feb,marc
*/
if (endDate.getYear() - beginDate.getYear() == 1) {
if ((beginDate.getMonthOfYear() == 12)
&& ((endDate.getMonthOfYear() == 1
|| endDate.getMonthOfYear() == 2 || endDate
.getMonthOfYear() == 3))) {
logger.info("return true different year");
return true;
}
/*
* Same year can be if begin and end date is december or begin and
* and date is jan,febr,marc TODO REMOVE Auto formatter
*/
} else if (endDate.getYear() - beginDate.getYear() == 0) {
if ((beginDate.getMonthOfYear() == 12 && endDate.getMonthOfYear() == 12)
|| ((beginDate.getMonthOfYear() == 1
|| beginDate.getMonthOfYear() == 2 || beginDate
.getMonthOfYear() == 3) && (endDate
.getMonthOfYear() == 1
|| endDate.getMonthOfYear() == 2 || endDate
.getMonthOfYear() == 3))) {
logger.info("return true same year");
return true;
}
}
logger.info("return false");
return false;
}
Joda-Time
Joda-Time and its Interval class with the overlap method is just what you need. Very easy.
Time Zone
Unlike java.util.Date, a DateTime truly knows its assigned time zone. Generally better to specify than rely on default. Note that if you are tracking date+time (a DateTime rather than a LocalDate), then time zone is critical. The definition of a "day" beginning and ending depends on time zone. Businesses that work across time zones may choose to use UTC for this purpose.
Span of Time
FYI, besides Interval, Joda-Time also offers the Period and Duration classes for working with a span of time.
Start of Day
When working with date-time values but focusing on a "day", then adjust the time portion to the first moment of the day for that particular time zone. In Joda-Time, simply call the withTimeAtStartOfDay method.
Avoid the "midnight"-related classes and methods. They are no longer recommended by the Joda-Time team.
Half-Open
Joda-Time uses the "Half-Open" approach when comparing spans of time. The beginning in inclusive and the ending is exclusive. That means since you want from December 1 to March 31 that we define an Interval of the first moment of the day of December 1 to the first moment of the day of April 1. If you ponder this, and search StackOverflow for other postings on "joda interval", you'll come to see the wisdom of this approach.
Comparison
The Interval class offers handy comparison methods: contains, abuts, overlap, and gap. Be sure to read the doc to understand exact details.
java.time
Java 8 brings the new java.time package, inspired by Joda-Time, defined by JSR 310. Joda-Time continues to work in Java 8, but you may want to learn java.time rather than Joda-Time if you are new to date-time work.
Example Code
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Budapest" ); // Or, perhaps DateTimeZone.UTC
// Inputs
DateTime contractStart = new DateTime( 2014, 1, 2, 0, 0, 0, timeZone );
DateTime contractStop = new DateTime( 2014, 5, 6, 0, 0, 0, timeZone );
Interval contractInterval = new Interval( contractStart, contractStop );
// Target to test
DateTime targetStart = new DateTime( 2013, DateTimeConstants.DECEMBER, 1, 0, 0, 0, timeZone );
DateTime targetStop = targetStart.plusMonths( 4 );
Interval targetInterval = new Interval( targetStart, targetStop );
boolean targetContainsContract = targetInterval.contains( contractInterval );
boolean targetOverlapsContract = ( targetInterval.overlap( contractInterval ) != null );
Dump to console…
System.out.println( "contractInterval: " + contractInterval );
System.out.println( "targetInterval: " + targetInterval );
System.out.println( "targetContainsContract: " + targetContainsContract );
System.out.println( "targetOverlapsContract: " + targetOverlapsContract );
When run…
contractInterval: 2014-01-02T00:00:00.000+01:00/2014-05-06T00:00:00.000+02:00
targetInterval: 2013-12-01T00:00:00.000+01:00/2014-04-01T00:00:00.000+02:00
targetContainsContract: false
targetOverlapsContract: true
Create an interval with the beginning and end date you get as inputs.
Create an interval going from March to December.
Your condition is true if either:
the march to december interval entirely contains the input interval,
or there is no overlap between the two intervals.
In code that would be:
marchToDecember.contains(interval) || marchToDecember.overlap(interval) == null
Javadàoc for Interval
Since you mention that the dates will be either both in or both out the period, you'll only need to test one of them.
So just test whether beginDate.getMonthOfYear() returns either 12, 1, 2 or 3.
I am working on an app where I store some information between each use, this data essentially boils down to counting the number of times an event has happened today, this week, this month and in the apps lifetime. I store this data in 4 distinct counters I can load/save using SharedPreferences.
Alongside the data I store the "last run time" of the app as a date, my plan was that during load time I will load in the counters then test the stored date against today's date to determine which counters need to be cleared.
Sounds simple right!
After pulling my hair out for a while and going backward and forwards through the Calendar documentation I think I understand them enough to come up with the following:
Calendar last = Calendar.getInstance();
last.setTimeInMillis(lastDate);
Calendar today = Calendar.getInstance();
today.add(Calendar.DATE, -1);
if ( !last.after(today) )
{
today = 0;
}
today.add(Calendar.WEEK_OF_MONTH, -1);
today.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
if ( !last.after(today) )
{
today = 0;
week = 0;
}
today = Calendar.getInstance();
today.add(Calendar.MONTH, -1);
today.set(Calendar.DATE, today.getActualMaximum(Calendar.DATE));
if ( !last.after(today) )
{
today = 0;
week = 0;
month = 0;
}
I think this should be fine, however the issue I have is testing, testing today is easy, however testing the month logic would require either waiting a month, or writing a test case which uses the Calendar API to simulate an old date, however I can't write the test case if my assumptions on how the API works was wrong in the first place!
Therefore, after a large wall of text my question is... does the above block of code look sane, or have I completely mis-understood working with dates in Java?
Thanks!
Edit:
Second pass at the code:
Does this look any more sensible? If I am understanding things correctly I am now attempting to compare the end of the date that was last saved with the very start of today, this week and this month.
Calendar last = Calendar.getInstance();
last.setTimeInMillis(lastDate);
last.set(Calendar.HOUR_OF_DAY, last.getActualMaximum(Calendar.HOUR_OF_DAY));
last.set(Calendar.MINUTE, last.getActualMaximum(Calendar.MINUTE));
last.set(Calendar.SECOND, last.getActualMaximum(Calendar.SECOND));
last.set(Calendar.MILLISECOND, last.getActualMaximum(Calendar.MILLISECOND));
Calendar todayStart = Calendar.getInstance();
todayStart.set(Calendar.HOUR_OF_DAY, todayStart.getActualMinimum(Calendar.HOUR_OF_DAY));
todayStart.set(Calendar.MINUTE, todayStart.getActualMinimum(Calendar.MINUTE));
todayStart.set(Calendar.SECOND, todayStart.getActualMinimum(Calendar.SECOND));
todayStart.set(Calendar.MILLISECOND, todayStart.getActualMinimum(Calendar.MILLISECOND));
// If the last recorded date was before the absolute minimum of today
if ( last.before(todayStart) )
{
todayCount = 0;
}
Calendar thisWeekStart = Calendar.getInstance();
thisWeekStart.set(Calendar.HOUR_OF_DAY, thisWeekStart.getActualMinimum(Calendar.HOUR_OF_DAY));
thisWeekStart.set(Calendar.MINUTE, thisWeekStart.getActualMinimum(Calendar.MINUTE));
thisWeekStart.set(Calendar.SECOND, thisWeekStart.getActualMinimum(Calendar.SECOND));
thisWeekStart.set(Calendar.DAY_OF_WEEK, thisWeekStart.getFirstDayOfWeek());
thisWeekStart.set(Calendar.MILLISECOND, thisWeekStart.getActualMinimum(Calendar.MILLISECOND));
// If the last date was before the absolute minimum of this week then clear
// this week (and today, just to be on the safe side)
if ( last.before(thisWeekStart) )
{
todayCount = 0;
weekCount = 0;
}
Calendar thisMonthStart = Calendar.getInstance();
thisMonthStart.set(Calendar.HOUR_OF_DAY, thisMonthStart.getActualMinimum(Calendar.HOUR_OF_DAY));
thisMonthStart.set(Calendar.MINUTE, thisMonthStart.getActualMinimum(Calendar.MINUTE));
thisMonthStart.set(Calendar.SECOND, thisMonthStart.getActualMinimum(Calendar.SECOND));
thisMonthStart.set(Calendar.DAY_OF_MONTH, thisMonthStart.getActualMinimum(Calendar.MONTH));
thisMonthStart.set(Calendar.MILLISECOND, thisMonthStart.getActualMinimum(Calendar.MILLISECOND));
// If the last date was before the absolute minimum of this month then clear month...
if ( !last.after(thisMonthStart) )
{
todayCount = 0;
weekCount = 0;
monthCount = 0;
}
Other than the readability challenges of using a variable called "today" and setting it to all manner of things that aren't "Today", you're not handling the time.
If it's now 3:20, and something happened at 5:00pm on Jan 31st, we probably want to still count that as happening in January? You should max out the time related fields to the end of the day as well.
For the week thing, that can be a real mess if someone executes in a locale where Sunday is considered the first day of the week. You may want to consider using the system's first day of week, rather than Sunday.
Also it is probably worth noting that this depends explicitly on the use of Calendar.add() to work properly. cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) -1); is NOT the same thing and would be broken.
You should just use Joda-Time. If you do your code becomes:
DateTime oneMonthAgo = new DateTime().minusMonths(1);
DateTime oneWeekAgo = new DateTime().minusWeeks(1);
And so on... It requires no further dependencies than the JDK itself and works on Android. Hope that helps.
Yes, you can use Joda-Time on Android. (From what I've read; I don't use Android)
Yes, you should be using Joda-Time. Far more advanced and useful that the notoriously troublesome java.util.Date and .Calendar classes bundled with Java.
Both your question and the other answers are ignoring the crucial issue of time zone. The time zone defines the meaning of "today" and the beginning/ending of other days.
You should define in plain declarative sentences exactly what you mean by "today", "this week", and "this month". For example, "today"…
Do you mean the last 24 hours?
Do you mean from 00:00:00 and up to but not including 00:00:00 tomorrow, in the UTC/GMT time zone (that is, no time zone offset)?
Do mean from the first moment of today in a given time zone (some offset from UTC) up to but not including the first moment of tomorrow in the same time zone? This may not be 24 hours because of Daylight Saving Time (DST) or other anomalies.
I'm too tired to parse your code. And I shouldn't have to. Before writing such date-time code, you should spell out in plain English what your goal is. Date-time work is surprisingly tricky, so you must be clear on your goals.
Here's some example code in Joda-Time 2.3.
Joda-Time uses the ISO 8601 standard for most defaults. This includes the definition of a week. Monday is first day, numbered 1, and Sunday is last day, numbered 7.
When focusing on a "day" with date-time objects, you may want to start with the first moment of the day. If so, call the withTimeAtStartOfDay method. To get end-of-day, don't. Use the Half-Open approach where you compare up to but not including the first moment of the next day. Explanation is found in other answers on StackOverflow.
Joda-Time offers 3 classes to handle spans of time: Period, Duration, and Interval. Check them all out. When doing comparisons, Joda-Time uses the "Half-Open" approach where the beginning is inclusive and the ending is exclusive. This makes sense when you ponder it. Search StackOverflow for more discussion.
Here's a bit of example code to get you going. I take a set of arbitrary date-time values. Then I define some spans of time as a day, week ago, and month ago. Then I count how many of the values fall into those spans.
String input = "2014-01-02T03:04:05Z";
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
java.util.List<DateTime> dateTimes = new java.util.ArrayList<DateTime>();
DateTime dateTime1 = new DateTime( input, timeZone ); // Parse the string as being in Zulu time zone (UTC). Then adjust to Montréal time.
dateTimes.add( dateTime1 );
dateTimes.add( dateTime1.plusDays( 3 ) );
dateTimes.add( dateTime1.plusWeeks( 1 ) );
dateTimes.add( dateTime1.plusMonths( 1 ) );
DateTime now = new DateTime( timeZone );
dateTimes.add( now );
dateTimes.add( now.minusDays( 1 ) );
dateTimes.add( now.minusDays( 10 ) );
// Spans of time
Interval today = new Interval( now.withTimeAtStartOfDay(), now.plusDays( 1 ).withTimeAtStartOfDay() );
Interval pastWeek = new Interval( now.minusWeeks( 1 ).withTimeAtStartOfDay(), now.plusDays( 1 ).withTimeAtStartOfDay() );
Interval pastMonth = new Interval( now.minusMonths( 1 ).withTimeAtStartOfDay(), now.plusDays( 1 ).withTimeAtStartOfDay() );
int countTotal = dateTimes.size();
int countDay = 0;
int countWeek = 0;
int countMonth = 0;
for ( DateTime dateTime : dateTimes ) {
if ( today.contains( dateTime ) ) {
countDay++;
}
if ( pastWeek.contains( dateTime ) ) {
countWeek++;
}
if ( pastMonth.contains( dateTime ) ) {
countMonth++;
}
}
Dump to console…
System.out.println( "dateTimes: " + dateTimes );
System.out.println( "today: " + today );
System.out.println( "pastWeek: " + pastWeek );
System.out.println( "pastMonth: " + pastMonth );
System.out.println( "countTotal: " + countTotal );
System.out.println( "countDay: " + countDay );
System.out.println( "countWeek: " + countWeek );
System.out.println( "countMonth: " + countMonth );
When run…
dateTimes: [2014-01-01T22:04:05.000-05:00, 2014-01-04T22:04:05.000-05:00, 2014-01-08T22:04:05.000-05:00, 2014-02-01T22:04:05.000-05:00, 2014-03-05T07:40:25.508-05:00, 2014-03-04T07:40:25.508-05:00, 2014-02-23T07:40:25.508-05:00]
today: 2014-03-05T00:00:00.000-05:00/2014-03-06T00:00:00.000-05:00
pastWeek: 2014-02-26T00:00:00.000-05:00/2014-03-06T00:00:00.000-05:00
pastMonth: 2014-02-05T00:00:00.000-05:00/2014-03-06T00:00:00.000-05:00
countTotal: 7
countDay: 1
countWeek: 2
countMonth: 3