Hi Mike,
This looks like something I tried to implement a while back -
nextMatching(). That is, given a DateTime, find the next DateTime that
matches the given Partial.
I got this working for dates, but I ran into problems with timezones.
Timezones were essentially unpredictable, and confused the definition of
what 'next matching' meant (eg. when DST rules lead to overlapping
hours). As a result, I stopped work on this concept.
This is some of the code I wrote, and was on the BaseDateTimeField
class. It was then overridden in subclasses to improve performance.
Basically, if we only implemented this for the Local* classes, then this
would be easy. Its the timezone thats the hard problem to solve.
Stephen
//------------------------------------------------------------------------
/**
* Finds the next instant that the input instant has the specified
value.
* <p>
* The value of this field will be set into the input milliseconds.
* The result will always be after the input milliseconds.
* If the value is invalid, an exception if thrown.
* <p>
* Finding the next match avoids changing other fields, especially
smaller
* sized ones. For exampe, finding the next 30th dayOfMonth after
the 31st
* January will return the 31st March. The time fields will be
unaltered.
*
* @param instant the milliseconds from 1970-01-01T00:00:00Z to set in
* @param value the value to set, in the units of the field
* @param numberOfRanges the number of ranges to move by, zero has
no effect
* @param firstMustChange whether the set must change the date
* @return the updated milliseconds
* @throws IllegalArgumentException if the value is invalid
* @since 1.3
*/
public long next(long instant, int value, int numberOfRanges,
boolean firstMustChange) {
if (numberOfRanges == 0) {
return instant;
}
long millis = set(instant, value);
if (numberOfRanges > 0) {
if (millis > instant || (millis == instant &&
!firstMustChange)) {
numberOfRanges--;
}
if (numberOfRanges > 0) {
millis = findNext(millis, value, numberOfRanges);
}
} else {
if (millis < instant || (millis == instant &&
!firstMustChange)) {
numberOfRanges++;
}
if (numberOfRanges < 0) {
millis = findNext(millis, value, numberOfRanges);
}
}
return millis;
}
/**
* Finds the next/previous occurrance of a value.
*
* @param millis the milliseconds with a field value equal to value
* @param value the value to progress to
* @param numberOfRanges the number of progressions, non-zero
* @return the updated millis
* @since 1.3
*/
protected long findNext(long millis, int value, int numberOfRanges) {
DurationField range = getRangeDurationField();
if (range == null || range.isSupported() == false) {
throw new IllegalFieldValueException(getType(),
Integer.toString(value));
}
int sgn = 1;
if (numberOfRanges < 0) {
sgn = -1;
numberOfRanges = -numberOfRanges;
}
// need to handle varying unit/range lengths
long base = millis;
for (int j = sgn; numberOfRanges > 0; j += sgn) {
millis = range.add(base, j);
if (get(millis) == value) {
numberOfRanges--;
}
}
return millis;
}
reece wrote:
> Hi Joda People,
>
> Pleases us this API generally does ;-)
>
> The bottom line (I think) is - How do I 'roll' a DateTime forward to the
> next
> occuring Partial (eg 1st October)?
>
> Some other details follow that illustrate the higher problem in case there
> is a better approach...
>
> My highish aim is:
> I have MyPartial of 1st October with just those fields set.
> I wish to split MyInterval around MyPartial, if of course it contains it.
> I don't see any ambiguity there.
>
> 2006-01-01 - 2007-07-01 false
> 2007-07-01 - 2007-10-02 true
>
> There must be a simpler way but at the moment I'm going through this
> procedure.
>
> Sub aim: Convert MyPartial to DateTime of the next year after
> MyInterval.start
> So I expected to be able to do some rounding to achieve this - I drew a
> blank.
> Instead I can first artificially add 3 months (1,Jan minus 1,Oct) to
> MyInterval.start and then roundFloor() the year - this gives a year I can
> extract and set on MyPartial, allowing a meaningful MyInstant to be
> extracted.
>
> Using this the following all result in the correct year to set on MyPartial
> in order to give me a date I can split MyInterval around.
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> MyInterval.start: Wed 1 Nov '06
> plusMonths(3): Thu 1 Feb '07
> year().roundFloor(): Mon 1 Jan '07
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> MyInterval.start: Thu 1 Feb '07
> plusMonths(3): Tue 1 May '07
> year().roundFloor(): Mon 1 Jan '07
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> MyInterval.start: Sun 1 Jul '07
> plusMonths(3): Mon 1 Oct '07
> year().roundFloor(): Mon 1 Jan '07
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> MyInterval.start: Sun 30 Sep '07
> plusMonths(3): Sun 30 Dec '07
> year().roundFloor(): Mon 1 Jan '07
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> MyInterval.start: Mon 1 Oct '07
> plusMonths(3): Tue 1 Jan '08
> year().roundFloor(): Tue 1 Jan '08
>
> The problem is, calculating the 3 month period (or whatever period that
> is depending on MyPartial) since MyPartial may be any point in the year.
> I see I can do:
> Days.daysBetween(ReadablePartial start,ReadablePartial end)
> Which may help but if MyPartial is < 29 Feb then this is going to cause
> error. In fact I expect that method would fallover without year field in the
> Partial.
>
> So the bottom line is - how do I roll a DateTime forward to the next
> occuring Partial?
>
> Thanks,
> Mike W
>
> P.S. Fantastic API - I'll never use that festering JDK library again!!
>
>
>
>
> -------------------------------------------------------------------------
> Take Surveys. Earn Cash. Influence the Future of IT
> Join SourceForge.net's Techsay panel and you'll get the chance to share your
> opinions on IT & business topics through brief surveys - and earn cash
> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
> _______________________________________________
> Joda-interest mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/joda-interest
>
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Joda-interest mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/joda-interest