Skip to content
Snippets Groups Projects
Commit a11a3d9e authored by Rene Redler's avatar Rene Redler
Browse files

update of mtime, taken from Luis

Fix bug for multi-month and -year event intervals (missing code).
2c7e74 and 761995
parent 7c55c33d
No related branches found
No related tags found
No related merge requests found
......@@ -24,10 +24,8 @@
#include "mtime_eventList.h"
#include "mtime_iso8601.h"
/* Local static functions. */
static
struct _datetime*
static struct _datetime*
getEventFirstTriggerDateTime(struct _datetime*, struct _timedelta*, struct _timedelta*, struct _datetime*, struct _datetime*);
// The IDs are unique only when they are live. Once a group/event has been deleted, the IDs will be reused.
......@@ -663,18 +661,8 @@ isCurrentEventActive(struct _event* event, struct _datetime* current_dt, struct
if (event->eventsLastEvaluationDateTime != NULL)
{
// fprintf(stderr, "LK test: check for equality ...\n");
// {
// char trigger_time[MAX_DATETIME_STR_LEN];
// datetimeToString(current_dt, trigger_time);
// fprintf(stderr, "LK test: test time %s ...\n", trigger_time);
// memset(trigger_time, 0, (size_t) MAX_DATETIME_STR_LEN);
// datetimeToString(event->eventsLastEvaluationDateTime, trigger_time);
// fprintf(stderr, "LK test: evaluate time %s ...\n", trigger_time);
// }
if (compareDatetime(current_dt, event->eventsLastEvaluationDateTime) == equal_to)
{
// fprintf(stderr, "LK test: return true ...\n");
return true;
}
}
......@@ -812,16 +800,8 @@ isCurrentEventActive(struct _event* event, struct _datetime* current_dt, struct
{
event->eventsLastEvaluationDateTime = newDateTime(initDummyDTString);
}
// fprintf(stderr, "LK test: copy ...\n");
event->eventsLastEvaluationDateTime = replaceDatetime(current_dt, event->eventsLastEvaluationDateTime);
// {
// char trigger_time[MAX_DATETIME_STR_LEN];
// datetimeToString(current_dt, trigger_time);
// fprintf(stderr, "LK test: trigger time %s ...\n", trigger_time);
// datetimeToString(event->eventsLastEvaluationDateTime, trigger_time);
// fprintf(stderr, "LK copy: evaluate time %s ...\n", trigger_time);
// }
// fprintf(stderr, "LK test: return true ...\n");
return true;
}
......@@ -981,221 +961,295 @@ static
struct _datetime*
getEventFirstTriggerDateTime(struct _datetime* start_dt, struct _timedelta* timestep, struct _timedelta* offset, struct _datetime* ref_dt, struct _datetime* first_trigger_dt)
{
if ((start_dt != NULL) && (timestep != NULL) && (ref_dt != NULL) && (first_trigger_dt != NULL) ){ //offset can be NULL.
/* NOTE: This code is higly 'rigged', to a point where it might feel micromanaged.
This is to speed-up the event-init process. Without the hack, the code
will be too slow and hence the ends justify the means.
*/
struct _timedelta* timestep_bkw;
/* Get start date in julian. */
struct _julianday* start_jd = newJulianDay(0, 0);
start_jd = date2julian(start_dt, start_jd);
/* Get timedelta in juliandelta. */
struct _juliandelta* timestep_jd = newJulianDelta('+', 0, 0);
timestep_jd = timeDeltaToJulianDelta(timestep, ref_dt, timestep_jd);
/* For speed-up */
struct _juliandelta* timestep_fastfwd_jd = newJulianDelta('+', 0, 0);
struct _juliandelta* timestep_fastbkw_jd = newJulianDelta('+', 0, 0);
/* Get anchor. ref + offset is the real anchor. */
struct _datetime* anchor = constructAndCopyDateTime(ref_dt);
addTimeDeltaToDateTime(ref_dt, offset, anchor); // Note: If offset is null, no addition takes place.
/* Get anchor in julian. */
struct _julianday* anchor_jd = newJulianDay(0, 0);
anchor_jd = date2julian(anchor, anchor_jd);
/* Optimization hack: Calculate an approx metric are_dates_too_far and speed up the jumps. */
int64_t are_dates_too_far = 0;
if (timestep_jd->day)
are_dates_too_far = (start_jd->day - anchor_jd->day)/(timestep_jd->day);
else if (timestep_jd->ms)
are_dates_too_far = (start_jd->day - anchor_jd->day)/((float)timestep_jd->ms/NO_OF_MS_IN_A_DAY);
//else ... well, should never happen. If it does, the initialized value of zero persists.
int lambda = 1; //speed-up const. Default is 1 or no speedup.
if (are_dates_too_far>10 || are_dates_too_far<-10)
lambda = 100000; //speed up if start-date and anchor are 'too-far' away.
/* Fast-Fwd */
timestep_fastfwd_jd->day = lambda*timestep_jd->day;
timestep_fastfwd_jd->ms = lambda*timestep_jd->ms;
while( timestep_fastfwd_jd->ms >= NO_OF_MS_IN_A_DAY )
{
timestep_fastfwd_jd->day++;
timestep_fastfwd_jd->ms = timestep_fastfwd_jd->ms - NO_OF_MS_IN_A_DAY;
}
/* We need to Loop backwards: Create a timestep replica and change the sign to negative to travel-back-in-time. */
timestep_bkw = constructAndCopyTimeDelta(timestep);
timestep_bkw->sign = '-';
struct _juliandelta* timestep_bkw_jd = newJulianDelta('+', 0, 0);
timeDeltaToJulianDelta(timestep_bkw, ref_dt, timestep_bkw_jd);
/* Fast-Bkwd */
timestep_fastbkw_jd->day = lambda*timestep_bkw_jd->day;
timestep_fastbkw_jd->ms = lambda*timestep_bkw_jd->ms;
while( timestep_fastbkw_jd->ms <= (-1)*(NO_OF_MS_IN_A_DAY) )
{
timestep_fastbkw_jd->day--;
timestep_fastbkw_jd->ms = timestep_fastbkw_jd->ms + NO_OF_MS_IN_A_DAY;
}
switch (compareDatetime(start_dt,ref_dt))
if ((start_dt != NULL) && (timestep != NULL) && (ref_dt != NULL) && (first_trigger_dt != NULL) ) //offset can be NULL.
{
case greater_than: /* start_dt > ref_dt */
/* Jump very fast and reach the start date quickly. */
do
{
anchor_jd->day = anchor_jd->day + timestep_fastfwd_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_fastfwd_jd->ms;
if (anchor_jd->ms >= NO_OF_MS_IN_A_DAY)
{
anchor_jd->day = anchor_jd->day + 1;
anchor_jd->ms = anchor_jd->ms - NO_OF_MS_IN_A_DAY;
}
} while ( !((anchor_jd->day > start_jd->day) || (anchor_jd->day == start_jd->day && anchor_jd->ms > start_jd->ms)) );
/* But I jumped one time too much. Move back */
anchor_jd->day = anchor_jd->day - timestep_fastfwd_jd->day;
anchor_jd->ms = anchor_jd->ms - timestep_fastfwd_jd->ms;
if (anchor_jd->ms < 0)
{
anchor_jd->day = anchor_jd->day - 1;
anchor_jd->ms = anchor_jd->ms + NO_OF_MS_IN_A_DAY;
}
/* I am close. Now determine the actual time. */
do
{
anchor_jd->day = anchor_jd->day + timestep_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_jd->ms;
if (timestep->year != 0 && timestep->month == 0 && timestep->day == 0
&& timestep->hour == 0 && timestep->minute == 0 && timestep->second == 0 && timestep->ms == 0)
{
/* NOTE: years only is a trivial case. */
if (anchor_jd->ms >= NO_OF_MS_IN_A_DAY)
{
anchor_jd->day = anchor_jd->day + 1;
anchor_jd->ms = anchor_jd->ms - NO_OF_MS_IN_A_DAY;
}
}while ( !((anchor_jd->day > start_jd->day) || (anchor_jd->day == start_jd->day && anchor_jd->ms >= start_jd->ms)) );
/* anchor_jd is now the true event-trigger-time. Set it to anchor. */
julian2date(anchor_jd,anchor);
break;
case equal_to: /* start_dt == ref_dt */
break;
case less_than: /* start_dt < ref_dt */
/* Jump very fast bkwd and reach the start date quickly. */
do
{
anchor_jd->day = anchor_jd->day + timestep_fastbkw_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_fastbkw_jd->ms;
if ( anchor_jd->ms < 0 )
{
anchor_jd->day = anchor_jd->day - 1;
anchor_jd->ms = anchor_jd->ms + NO_OF_MS_IN_A_DAY;
}
} while(! (anchor_jd->day < start_jd->day || (anchor_jd->day == start_jd->day && anchor_jd->ms < start_jd->ms)) );
/* I jumped one time too much. Move forward. */
anchor_jd->day = anchor_jd->day + timestep_fastfwd_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_fastfwd_jd->ms;
if (anchor_jd->ms >= NO_OF_MS_IN_A_DAY)
{
anchor_jd->day = anchor_jd->day + 1;
anchor_jd->ms = anchor_jd->ms - NO_OF_MS_IN_A_DAY;
}
/* I am close. Get the real time. */
do
{
anchor_jd->day = anchor_jd->day + timestep_bkw_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_bkw_jd->ms;
if ( anchor_jd->ms < 0 )
{
anchor_jd->day = anchor_jd->day - 1;
anchor_jd->ms = anchor_jd->ms + NO_OF_MS_IN_A_DAY;
}
} while(! (anchor_jd->day < start_jd->day || (anchor_jd->day == start_jd->day && anchor_jd->ms < start_jd->ms)) );
/* I jumped one time too much. Move forward. */
anchor_jd->day = anchor_jd->day + timestep_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_jd->ms;
if (anchor_jd->ms >= NO_OF_MS_IN_A_DAY)
{
anchor_jd->day = anchor_jd->day + 1;
anchor_jd->ms = anchor_jd->ms - NO_OF_MS_IN_A_DAY;
}
/* Get anchor. ref + offset is the real anchor. */
struct _datetime *anchor = constructAndCopyDateTime(ref_dt);
addTimeDeltaToDateTime(ref_dt, offset, anchor); // Note: If offset is null, no addition takes place.
/* Determine difference between anchor and start year */
int64_t differenceOfYears = start_dt->date.year - anchor->date.year; // result always >= 0.
int64_t yearsToAdd = differenceOfYears % timestep->year;
/* We only need to update the year */
replaceDatetime(start_dt, first_trigger_dt);
first_trigger_dt->date.year += yearsToAdd;
/* Cleanup. */
deallocateDateTime(anchor);
/* anchor_jd now has the true trigger time. Copy it to anchor. */
julian2date(anchor_jd,anchor);
/* And return. */
return first_trigger_dt;
}
else if (timestep->year == 0 && timestep->month != 0 && timestep->day == 0
&& timestep->hour == 0 && timestep->minute == 0 && timestep->second == 0 && timestep->ms == 0)
{
/* NOTE: months only is again a trivial case. */
/* Get anchor. ref + offset is the real anchor. */
struct _datetime *anchor = constructAndCopyDateTime(ref_dt);
addTimeDeltaToDateTime(ref_dt, offset, anchor); // Note: If offset is null, no addition takes place.
/* Determine difference between anchor and start in months */
int differenceOfMonths = 12*(start_dt->date.year - anchor->date.year) + start_dt->date.month - anchor->date.month;
int yearsToAdd = differenceOfMonths / 12;
int monthsToAdd = differenceOfMonths % timestep->month;
/* We only need to update the year */
replaceDatetime(anchor, first_trigger_dt);
first_trigger_dt->date.year += yearsToAdd;
first_trigger_dt->date.month += monthsToAdd;
default:
/* Cleanup. */
deallocateDateTime(anchor);
; //Should never happen. Don't return NULL just yet as deallocateDateTime(anchor) still needs to be called.
/* And return. */
return first_trigger_dt;
}
else if (timestep->year == 0 && timestep->month == 0)
{
/* NOTE: This code is higly 'rigged', to a point where it might feel micromanaged.
This is to speed-up the event-init process. Without the hack, the code
will be too slow and hence the ends justify the means.
*/
struct _timedelta* timestep_bkw;
/* Get start date in julian. */
struct _julianday* start_jd = newJulianDay(0, 0);
start_jd = date2julian(start_dt, start_jd);
/* Get timedelta in juliandelta. */
struct _juliandelta* timestep_jd = newJulianDelta('+', 0, 0);
timestep_jd = timeDeltaToJulianDelta(timestep, ref_dt, timestep_jd);
/* For speed-up */
struct _juliandelta* timestep_fastfwd_jd = newJulianDelta('+', 0, 0);
struct _juliandelta* timestep_fastbkw_jd = newJulianDelta('+', 0, 0);
/* Get anchor. ref + offset is the real anchor. */
struct _datetime* anchor = constructAndCopyDateTime(ref_dt);
addTimeDeltaToDateTime(ref_dt, offset, anchor); // Note: If offset is null, no addition takes place.
/* Get anchor in julian. */
struct _julianday* anchor_jd = newJulianDay(0, 0);
anchor_jd = date2julian(anchor, anchor_jd);
/* Optimization hack: Calculate an approx metric are_dates_too_far and speed up the jumps. */
int64_t are_dates_too_far = 0;
if (timestep_jd->day)
are_dates_too_far = (start_jd->day - anchor_jd->day)/(timestep_jd->day);
else if (timestep_jd->ms)
are_dates_too_far = (start_jd->day - anchor_jd->day)/((float)timestep_jd->ms/NO_OF_MS_IN_A_DAY);
//else ... well, should never happen. If it does, the initialized value of zero persists.
int lambda = 1; //speed-up const. Default is 1 or no speedup.
if (are_dates_too_far>10 || are_dates_too_far<-10)
lambda = 100000; //speed up if start-date and anchor are 'too-far' away.
/* Fast-Fwd */
timestep_fastfwd_jd->day = lambda*timestep_jd->day;
timestep_fastfwd_jd->ms = lambda*timestep_jd->ms;
while( timestep_fastfwd_jd->ms >= NO_OF_MS_IN_A_DAY )
{
timestep_fastfwd_jd->day++;
timestep_fastfwd_jd->ms = timestep_fastfwd_jd->ms - NO_OF_MS_IN_A_DAY;
}
/* We need to Loop backwards: Create a timestep replica and change the sign to negative to travel-back-in-time. */
timestep_bkw = constructAndCopyTimeDelta(timestep);
timestep_bkw->sign = '-';
struct _juliandelta* timestep_bkw_jd = newJulianDelta('+', 0, 0);
timeDeltaToJulianDelta(timestep_bkw, ref_dt, timestep_bkw_jd);
/* Fast-Bkwd */
timestep_fastbkw_jd->day = lambda*timestep_bkw_jd->day;
timestep_fastbkw_jd->ms = lambda*timestep_bkw_jd->ms;
while( timestep_fastbkw_jd->ms <= (-1)*(NO_OF_MS_IN_A_DAY) )
{
timestep_fastbkw_jd->day--;
timestep_fastbkw_jd->ms = timestep_fastbkw_jd->ms + NO_OF_MS_IN_A_DAY;
}
switch (compareDatetime(start_dt,ref_dt))
{
case greater_than: /* start_dt > ref_dt */
/* Jump very fast and reach the start date quickly. */
do
{
anchor_jd->day = anchor_jd->day + timestep_fastfwd_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_fastfwd_jd->ms;
if (anchor_jd->ms >= NO_OF_MS_IN_A_DAY)
{
anchor_jd->day = anchor_jd->day + 1;
anchor_jd->ms = anchor_jd->ms - NO_OF_MS_IN_A_DAY;
}
} while ( !((anchor_jd->day > start_jd->day) || (anchor_jd->day == start_jd->day && anchor_jd->ms > start_jd->ms)) );
/* But I jumped one time too much. Move back */
anchor_jd->day = anchor_jd->day - timestep_fastfwd_jd->day;
anchor_jd->ms = anchor_jd->ms - timestep_fastfwd_jd->ms;
if (anchor_jd->ms < 0)
{
anchor_jd->day = anchor_jd->day - 1;
anchor_jd->ms = anchor_jd->ms + NO_OF_MS_IN_A_DAY;
}
/* I am close. Now determine the actual time. */
do
{
anchor_jd->day = anchor_jd->day + timestep_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_jd->ms;
if (anchor_jd->ms >= NO_OF_MS_IN_A_DAY)
{
anchor_jd->day = anchor_jd->day + 1;
anchor_jd->ms = anchor_jd->ms - NO_OF_MS_IN_A_DAY;
}
} while ( !((anchor_jd->day > start_jd->day) || (anchor_jd->day == start_jd->day && anchor_jd->ms >= start_jd->ms)) );
/* anchor_jd is now the true event-trigger-time. Set it to anchor. */
julian2date(anchor_jd,anchor);
break;
case equal_to: /* start_dt == ref_dt */
break;
case less_than: /* start_dt < ref_dt */
/* Jump very fast bkwd and reach the start date quickly. */
do
{
anchor_jd->day = anchor_jd->day + timestep_fastbkw_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_fastbkw_jd->ms;
if ( anchor_jd->ms < 0 )
{
anchor_jd->day = anchor_jd->day - 1;
anchor_jd->ms = anchor_jd->ms + NO_OF_MS_IN_A_DAY;
}
} while(! (anchor_jd->day < start_jd->day || (anchor_jd->day == start_jd->day && anchor_jd->ms < start_jd->ms)) );
/* I jumped one time too much. Move forward. */
anchor_jd->day = anchor_jd->day + timestep_fastfwd_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_fastfwd_jd->ms;
if (anchor_jd->ms >= NO_OF_MS_IN_A_DAY)
{
anchor_jd->day = anchor_jd->day + 1;
anchor_jd->ms = anchor_jd->ms - NO_OF_MS_IN_A_DAY;
}
/* I am close. Get the real time. */
do
{
anchor_jd->day = anchor_jd->day + timestep_bkw_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_bkw_jd->ms;
if ( anchor_jd->ms < 0 )
{
anchor_jd->day = anchor_jd->day - 1;
anchor_jd->ms = anchor_jd->ms + NO_OF_MS_IN_A_DAY;
}
} while(! (anchor_jd->day < start_jd->day || (anchor_jd->day == start_jd->day && anchor_jd->ms < start_jd->ms)) );
/* I jumped one time too much. Move forward. */
anchor_jd->day = anchor_jd->day + timestep_jd->day;
anchor_jd->ms = anchor_jd->ms + timestep_jd->ms;
if (anchor_jd->ms >= NO_OF_MS_IN_A_DAY)
{
anchor_jd->day = anchor_jd->day + 1;
anchor_jd->ms = anchor_jd->ms - NO_OF_MS_IN_A_DAY;
}
/* anchor_jd now has the true trigger time. Copy it to anchor. */
julian2date(anchor_jd,anchor);
default:
; //Should never happen. Don't return NULL just yet as deallocateDateTime(anchor) still needs to be called.
}
/* Copy the contents to target. */
replaceDatetime(anchor,first_trigger_dt);
/* Cleanup. */
deallocateDateTime(anchor);
deallocateJulianDay(start_jd);
deallocateJulianDay(anchor_jd);
deallocateJulianDelta(timestep_jd);
deallocateTimeDelta(timestep_bkw);
deallocateJulianDelta(timestep_bkw_jd);
deallocateJulianDelta(timestep_fastfwd_jd);
deallocateJulianDelta(timestep_fastbkw_jd);
/* And return. */
return first_trigger_dt;
}
else
{
/* NOTE: general case updates by explicit adding. */
/* Get anchor. ref + offset is the real anchor. */
struct _datetime *anchor = constructAndCopyDateTime(ref_dt);
addTimeDeltaToDateTime(ref_dt, offset, anchor); // Note: If offset is null, no addition takes place.
while (compareDatetime(anchor, start_dt) == less_than)
{
addTimeDeltaToDateTime(anchor, timestep, anchor);
}
/* Copy the contents to target. */
replaceDatetime(anchor,first_trigger_dt);
/* Cleanup. */
deallocateDateTime(anchor);
/* And return. */
return first_trigger_dt;
}
}
/* Copy the contents to target. */
replaceDatetime(anchor,first_trigger_dt);
/* Cleanup. */
deallocateDateTime(anchor);
deallocateJulianDay(start_jd);
deallocateJulianDay(anchor_jd);
deallocateJulianDelta(timestep_jd);
deallocateTimeDelta(timestep_bkw);
deallocateJulianDelta(timestep_bkw_jd);
deallocateJulianDelta(timestep_fastfwd_jd);
deallocateJulianDelta(timestep_fastbkw_jd);
/* And return. */
return first_trigger_dt;
}
else
return NULL;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment