* _xmlSchemaDateAdd: * @dt: an #xmlSchemaValPtr * @dur: an #xmlSchemaValPtr of type #XS_DURATION * * Compute a new date/time from @dt and @dur. This function assumes @dt * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH, * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as * @dt. The calling program is responsible for freeing the returned value
| 3910 | * Returns a pointer to a new #xmlSchemaVal or NULL if error. |
| 3911 | */ |
| 3912 | static xmlSchemaValPtr |
| 3913 | _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur) |
| 3914 | { |
| 3915 | xmlSchemaValPtr ret, tmp; |
| 3916 | long carry, tempdays, temp; |
| 3917 | xmlSchemaValDatePtr r, d; |
| 3918 | xmlSchemaValDurationPtr u; |
| 3919 | |
| 3920 | if ((dt == NULL) || (dur == NULL)) |
| 3921 | return NULL; |
| 3922 | |
| 3923 | ret = xmlSchemaNewValue(dt->type); |
| 3924 | if (ret == NULL) |
| 3925 | return NULL; |
| 3926 | |
| 3927 | /* make a copy so we don't alter the original value */ |
| 3928 | tmp = xmlSchemaDupVal(dt); |
| 3929 | if (tmp == NULL) { |
| 3930 | xmlSchemaFreeValue(ret); |
| 3931 | return NULL; |
| 3932 | } |
| 3933 | |
| 3934 | r = &(ret->value.date); |
| 3935 | d = &(tmp->value.date); |
| 3936 | u = &(dur->value.dur); |
| 3937 | |
| 3938 | /* normalization */ |
| 3939 | if (d->mon == 0) |
| 3940 | d->mon = 1; |
| 3941 | |
| 3942 | /* normalize for time zone offset */ |
| 3943 | u->sec -= (d->tzo * 60); |
| 3944 | d->tzo = 0; |
| 3945 | |
| 3946 | /* normalization */ |
| 3947 | if (d->day == 0) |
| 3948 | d->day = 1; |
| 3949 | |
| 3950 | /* month */ |
| 3951 | carry = d->mon + u->mon; |
| 3952 | r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13); |
| 3953 | carry = (long) FQUOTIENT_RANGE(carry, 1, 13); |
| 3954 | |
| 3955 | /* year (may be modified later) */ |
| 3956 | r->year = d->year + carry; |
| 3957 | if (r->year == 0) { |
| 3958 | if (d->year > 0) |
| 3959 | r->year--; |
| 3960 | else |
| 3961 | r->year++; |
| 3962 | } |
| 3963 | |
| 3964 | /* time zone */ |
| 3965 | r->tzo = d->tzo; |
| 3966 | r->tz_flag = d->tz_flag; |
| 3967 | |
| 3968 | /* seconds */ |
| 3969 | r->sec = d->sec + u->sec; |
no test coverage detected