Loading...
Searching...
No Matches
diff.c
Go to the documentation of this file.
/*
* Copyright (C) 1995. Bill Brown <brown@gis.uiuc.edu> & Michael Shapiro
*
* This program is free software under the GPL (>=v2)
* Read the file GPL.TXT coming with GRASS for details.
*/
#include <stdlib.h>
#include <grass/datetime.h>
#include "math.h"
/*************************************************************/
/*
This performs the formula: result = a - b;
both a and b must be absolute.
result will be relative
If a is "earlier" than b, then result should be set negative.
b must be no more "precise" than a.
(a copy of b is "extended" to the precision of a)
datetime_copy (tb, b)
datetime_reset_from_to (tb, b.from, a.to, a.fracsec))
If result.to == SECOND, then result.fracsec is a.fracsec
result will have the following from/to based on a.to:
result
a.to from to
YEAR YEAR YEAR
MONTH YEAR MONTH
DAY DAY DAY
HOUR DAY HOUR
MINUTE DAY MINUTE
SECOND DAY SECOND
If either 'a' or 'b' has a timezone, both must have a timezone.
The difference will account for the differences in the time zones.
*/
static int _datetime_ymd_to_ddays(const DateTime *, double *);
static int _datetime_compare(const DateTime *, const DateTime *);
/*!
* \brief
*
*
* This performs the formula: result = a - b;
* <ul>
<li> both a and b must be absolute.
* </li>
<li> result will be relative
* </li>
<li> If a is "earlier" than b, then result will be set negative.
* </li>
<li> b must be no more "precise" than a.
* (a copy of b is "extended" to the precision of a)
* </li>
<li> If result.to == SECOND, then result.fracsec is a.fracsec
* </li>
<li> result will have the following from/to based
* on a.to: result a.to from to YEAR YEAR YEAR MONTH YEAR
* MONTH DAY DAY DAY HOUR DAY HOUR MINUTE DAY
* MINUTE SECOND DAY SECOND [LAYOUT ??? - see HTML]
* </li>
<li> If either 'a' or 'b' has a timezone, both must have a timezone. The
* difference will account for the differences in the time zones.
</li></ul>
*
* \param a
* \param b
* \param result
* \return int
*/
int datetime_difference(const DateTime *a, const DateTime *b, DateTime *result)
{
DateTime tb, ta, *early, *late;
int compare, tzmin;
/* if not both absolute, return error */
datetime_copy(&tb, b);
datetime_change_from_to(&tb, DATETIME_YEAR, a->to, a->fracsec);
datetime_copy(&ta, a);
if (datetime_get_timezone(&ta, &tzmin) == 0 ||
datetime_get_timezone(&tb, &tzmin) == 0) {
if (datetime_get_timezone(&ta, &tzmin) == 0 &&
datetime_get_timezone(&tb, &tzmin) == 0) {
datetime_change_to_utc(&ta);
datetime_change_to_utc(&tb);
}
else
return datetime_error(-1,
"only one opperand contains valid timezone");
}
/* initialize result */
datetime_set_type(result, DATETIME_RELATIVE,
ta.to < DATETIME_DAY ? DATETIME_YEAR : DATETIME_DAY,
ta.to, ta.fracsec);
compare = _datetime_compare(&ta, &tb);
if (compare > 0) {
early = &tb;
late = &ta;
result->positive = 1;
}
else if (compare < 0) {
early = &ta;
late = &tb;
result->positive = 0;
}
else { /* equal */
return (0);
}
/* now the work */
if (datetime_in_interval_year_month(ta.to)) {
int dm;
if (ta.positive == tb.positive) {
/* change if we use doubles! */
result->year = abs(late->year - early->year);
}
else {
result->year = late->year + early->year - 2;
}
dm = late->month - early->month;
if (dm >= 0)
result->month = dm;
else {
result->year -= 1;
result->month = dm + 12;
}
}
else {
DateTime erel, lrel;
double latedays, earlydays;
datetime_set_increment_type(a, &erel);
_datetime_ymd_to_ddays(early, &earlydays);
/* copy day -> down */
erel.day = earlydays;
erel.hour = early->hour;
erel.minute = early->minute;
erel.second = early->second;
datetime_set_increment_type(a, &lrel);
_datetime_ymd_to_ddays(late, &latedays);
/* copy day -> down */
lrel.day = latedays;
lrel.hour = late->hour;
lrel.minute = late->minute;
lrel.second = late->second;
datetime_invert_sign(&erel);
datetime_increment(&erel, &lrel);
/* copy erel back to result */
result->day = erel.day;
result->hour = erel.hour;
result->minute = erel.minute;
result->second = erel.second;
/* need carry? */
}
return (0);
}
/*************************************************************/
/* returns 1 if a is later than b,
-1 if a is earlier than a,
0 otherwise
*/
/* only looks at from-to fields defined by a */
static int _datetime_compare(const DateTime *a, const DateTime *b)
{
int i;
if (a->positive && !b->positive)
return (1);
else if (b->positive && !a->positive)
return (-1);
/* same signs */
for (i = a->from; i <= a->to; i++) {
switch (i) {
case DATETIME_SECOND:
if (a->second > b->second)
return (1);
else if (a->second < b->second)
return (-1);
break;
case DATETIME_MINUTE:
if (a->minute > b->minute)
return (1);
else if (a->minute < b->minute)
return (-1);
break;
case DATETIME_HOUR:
if (a->hour > b->hour)
return (1);
else if (a->hour < b->hour)
return (-1);
break;
case DATETIME_DAY:
if (a->day > b->day)
return (1);
else if (a->day < b->day)
return (-1);
break;
case DATETIME_MONTH:
if (a->month > b->month)
return (1);
else if (a->month < b->month)
return (-1);
break;
case DATETIME_YEAR: /* only place sign matters */
if (a->positive) {
if (a->year > b->year)
return (1);
else if (a->year < b->year)
return (-1);
}
else {
if (a->year < b->year)
return (1);
else if (a->year > b->year)
return (-1);
}
break;
}
}
return (0);
}
/*************************************************************/
static int _datetime_ymd_to_ddays(const DateTime *dtymd, double *days)
{ /* note extra precision! */
int yr, mo;
*days = 0.0;
if (dtymd->positive) {
*days = dtymd->day - 1; /* start w/ days - 1 */
for (mo = dtymd->month - 1; mo > 0; mo--) { /* add earlier months */
*days += datetime_days_in_month(dtymd->year, mo, dtymd->positive);
}
for (yr = dtymd->year - 1; yr > 0; yr--) { /* add earlier years */
*days += datetime_days_in_year(yr, dtymd->positive);
}
}
else {
for (yr = dtymd->year - 1; yr > 0; yr--) { /* add later years */
*days += datetime_days_in_year(yr, dtymd->positive);
}
for (mo = 12; mo >= dtymd->month;
mo--) { /*add current & later months */
*days += datetime_days_in_month(dtymd->year, mo, dtymd->positive);
}
*days -= dtymd->day; /* subtract current days */
}
return 0;
}
/*************************************************************/
/*************************************************************/
datetime_change_from_to
int datetime_change_from_to(DateTime *dt, int from, int to, int round)
Changes the from/to of the type for dt. The 'from/to' must be legal values for the mode of dt; (if th...
Definition change.c:53
datetime_copy
void datetime_copy(DateTime *dst, const DateTime *src)
Copies the DateTime [into/from ???] src.
Definition copy.c:19
datetime_error
int datetime_error(int code, char *msg)
record 'code' and 'msg' as error code/msg (in static variables) code==0 will clear the error (ie set ...
Definition datetime/error.c:27
datetime_difference
int datetime_difference(const DateTime *a, const DateTime *b, DateTime *result)
This performs the formula: result = a - b;.
Definition diff.c:78
b
double b
Definition driver/set_window.c:5
datetime_increment
int datetime_increment(DateTime *src, DateTime *incr)
This function changes the 'src' date/time data based on the 'incr' The type (mode/from/to) of the 'sr...
Definition incr1.c:67
datetime_set_increment_type
int datetime_set_increment_type(const DateTime *src, DateTime *incr)
src must be legal This is a convenience routine which is implemented as follows:
Definition incr3.c:82
datetime_days_in_month
int datetime_days_in_month(int year, int month, int ad)
returns number of days in 'month' of a particular 'year'
Definition misc.c:58
datetime_days_in_year
int datetime_days_in_year(int year, int ad)
returns the number of days in 'year'
Definition misc.c:37
datetime_invert_sign
void datetime_invert_sign(DateTime *dt)
Definition sign.c:71
datetime_set_type
int datetime_set_type(DateTime *dt, int mode, int from, int to, int fracsec)
Definition type.c:36
datetime_in_interval_year_month
int datetime_in_interval_year_month(int x)
Definition type.c:145
datetime_get_timezone
int datetime_get_timezone(const DateTime *dt, int *minutes)
returns 0 on success
Definition tz1.c:44
datetime_change_to_utc
int datetime_change_to_utc(DateTime *dt)
Return datetime_change_timezone (dt, 0);.
Definition tz2.c:57