Skip to content
Snippets Groups Projects
Commit 7bd7bae6 authored by Luis Kornblueh's avatar Luis Kornblueh
Browse files

Handling of time spans of more than a month with timedelta division.

parent e15be5b6
No related branches found
No related tags found
No related merge requests found
......@@ -50,7 +50,7 @@ struct _timedelta
/* Used only for storing division of two time-delta results. */
struct _divisionquotienttimedelta
struct _divisionquotienttimespan
{
int64_t quotient;
int64_t remainder_in_ms;
......@@ -82,8 +82,11 @@ struct _timedelta*
julianDeltaToTimeDelta(struct _juliandelta* jd, struct _datetime *dt, struct _timedelta* td_return);
/*! \endcond */
struct _divisionquotienttimedelta*
divideTimeDeltaInSeconds(struct _timedelta* dividend, struct _timedelta* divisor, struct _divisionquotienttimedelta* quo_ret);
struct _divisionquotienttimespan*
divideTimeDeltaInSeconds(struct _timedelta* dividend, struct _timedelta* divisor, struct _divisionquotienttimespan* quo_ret);
struct _divisionquotienttimespan*
divideDatetimeDifferenceInSeconds(struct _datetime* dt1, struct _datetime* dt2, struct _timedelta* divisor, struct _divisionquotienttimespan* quo_ret);
struct _timedelta*
getTimeDeltaFromDate(struct _date*, struct _date*, struct _timedelta*);
......
......@@ -1031,7 +1031,7 @@ module mtime_timedelta
!
public :: max_timedelta_str_len
public :: timedelta
public :: divisionquotienttimedelta
public :: divisionquotienttimespan
public :: newTimedelta
public :: deallocateTimedelta
public :: getTimeDeltaFromDate
......@@ -1049,6 +1049,7 @@ module mtime_timedelta
public :: elementwiseScalarMultiplyTimeDeltaInv_long
public :: elementwiseAddTimeDeltatoTimeDelta
public :: divideTimeDeltaInSeconds
public :: divideDatetimeDifferenceInSeconds
public :: operator(+)
public :: operator(-)
public :: operator(*)
......@@ -1073,10 +1074,10 @@ module mtime_timedelta
integer(c_int) :: ms
end type timedelta
!
type, bind(c) :: divisionquotienttimedelta
type, bind(c) :: divisionquotienttimespan
integer(c_int64_t) :: quotient;
integer(c_int64_t) :: remainder_in_ms;
end type divisionquotienttimedelta
end type divisionquotienttimespan
!
interface newTimedelta
module procedure newtimedeltafromstring
......@@ -1283,6 +1284,16 @@ module mtime_timedelta
type(c_ptr), value :: quotient
end function my_divideTimeDeltaInSeconds
!
function my_divideDatetimeDifferenceInSeconds(dt1, dt2, divisor, quotient) result(ret_quotient) &
& bind(c,name='divideDatetimeDifferenceInSeconds')
import :: c_ptr
type(c_ptr) :: ret_quotient
type(c_ptr), value :: dt1
type(c_ptr), value :: dt2
type(c_ptr), value :: divisor
type(c_ptr), value :: quotient
end function my_divideDatetimeDifferenceInSeconds
!
end interface
!
contains
......@@ -1625,11 +1636,20 @@ contains
subroutine divideTimeDeltaInSeconds(dividend, divisor, quotient)
type(timedelta), target, intent(in) :: dividend
type(timedelta), target, intent(in) :: divisor
type(divisionquotienttimedelta), target, intent(out) :: quotient
type(divisionquotienttimespan), target, intent(out) :: quotient
type(c_ptr) :: dummy_ptr
dummy_ptr = my_dividetimedeltainseconds(c_loc(dividend), c_loc(divisor), c_loc(quotient))
end subroutine divideTimeDeltaInSeconds
!
subroutine divideDatetimeDifferenceInSeconds(dt1, dt2, divisor, quotient)
type(datetime), target, intent(in) :: dt1
type(datetime), target, intent(in) :: dt2
type(timedelta), target, intent(in) :: divisor
type(divisionquotienttimespan), target, intent(out) :: quotient
type(c_ptr) :: dummy_ptr
dummy_ptr = my_dividedatetimedifferenceinseconds(c_loc(dt1), c_loc(dt2), c_loc(divisor), c_loc(quotient))
end subroutine divideDatetimeDifferenceInSeconds
!
end module mtime_timedelta
!>
!! @brief Definition of the basic event type and its methods.
......
......@@ -1067,16 +1067,18 @@ else
/*! \endcond */
struct _divisionquotienttimedelta*
divideTimeDeltaInSeconds(struct _timedelta* dividend, struct _timedelta* divisor, struct _divisionquotienttimedelta* quo_ret)
struct _divisionquotienttimespan*
divideTimeDeltaInSeconds(struct _timedelta* dividend, struct _timedelta* divisor, struct _divisionquotienttimespan* quo_ret)
{
if ((dividend != NULL) && (divisor != NULL) && (quo_ret != NULL))
{
if ((dividend->year == 0) && (dividend->month == 0) && (divisor->year == 0) && (divisor->month == 0))
{
intmax_t numerator = (intmax_t) (((int64_t) dividend->day * 86400 + dividend->minute * 60 + dividend->second) * 1000 + dividend->ms);
intmax_t denominator = (intmax_t) (((int64_t) divisor->day * 86400 + divisor->minute * 60 + divisor->second ) * 1000 + divisor->ms);
intmax_t numerator = (intmax_t) (((int64_t) dividend->day * 86400 + dividend->hour * 3600 + dividend->minute * 60 + dividend->second) * 1000 + dividend->ms);
intmax_t denominator = (intmax_t) (((int64_t) divisor->day * 86400 + divisor->hour * 3600 +divisor->minute * 60 + divisor->second ) * 1000 + divisor->ms);
fprintf(stderr, "recalculated in ms: numerator %ld denominator %ld\n", numerator, denominator);
if (denominator == 0) /* Division by zero is illegal. */
return NULL;
......@@ -1085,12 +1087,68 @@ divideTimeDeltaInSeconds(struct _timedelta* dividend, struct _timedelta* divisor
quo_ret->quotient = (int64_t) div.quot;
quo_ret->remainder_in_ms = (int64_t) div.rem;
fprintf(stderr, "quotient %ld remainder %ld\n", quo_ret->quotient, quo_ret->remainder_in_ms);
return quo_ret;
}
else /* Only seconds supported */
return NULL;
}
else
return NULL;
}
/**
* @brief division by an interval given in of seconds.
*
* @param refdt
* Reference date (a pointer to struct _datetime).
* @param dt
* A pointer to struct _datetime.
* @param intvlsec
* Interval given in seconds.
*
* @return result of division. NULL indicates error.
*/
struct _divisionquotienttimespan*
divideDatetimeDifferenceInSeconds(struct _datetime* dt1, struct _datetime* dt2, struct _timedelta* divisor, struct _divisionquotienttimespan* quo_ret)
{
if ((dt1 != NULL) && (dt2 != NULL) && (divisor != NULL) && (quo_ret != NULL))
{
if ((divisor->year == 0) && (divisor->month == 0))
{
return NULL;
struct _julianday* jd1 = newJulianDay(0, 0);
if (jd1 != NULL) jd1 = date2julian(dt1, jd1);
struct _julianday* jd2 = newJulianDay(0, 0);
if (jd2 != NULL) jd2 = date2julian(dt2, jd2);
intmax_t denominator = (intmax_t) (((int64_t) divisor->day * 86400 + divisor->hour * 3600 +divisor->minute * 60 + divisor->second ) * 1000 + divisor->ms);
if (denominator == 0) /* Division by zero is illegal. */
return NULL;
struct _juliandelta* jd = newJulianDelta('+', 0, 0);
jd = substractJulianDay(jd1, jd2, jd);
intmax_t numerator = (intmax_t) (jd->day * 86400000 + jd->ms);
fprintf(stderr, "recalculated in ms: numerator %ld denominator %ld\n", numerator, denominator);
imaxdiv_t div = imaxdiv(numerator, denominator);
quo_ret->quotient = (int64_t) div.quot;
quo_ret->remainder_in_ms = (int64_t) div.rem;
fprintf(stderr, "quotient %ld remainder %ld\n", quo_ret->quotient, quo_ret->remainder_in_ms);
if (jd1 != NULL) deallocateJulianDay(jd1);
if (jd2 != NULL) deallocateJulianDay(jd2);
if (jd != NULL) deallocateJulianDelta(jd);
return quo_ret;
}
else
return NULL;
}
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