static void QtoD_ym(npy_int64 ordinal, int *y, int *m, asfreq_info *af_info) { *y = floordiv(ordinal, 4) + BASE_YEAR; *m = mod_compat(ordinal, 4) * 3 + 1; if (af_info->from_q_year_end != 12) { *m += af_info->from_q_year_end; if (*m > 12) { *m -= 12; } else { *y -= 1; } } }
/* returns 0 on success, 1 on error with errno set */ static int calc_lon(privpath_t *pp) { point_t *pt = pp->pt; int n = pp->len; int i, j, k, k1; int ct[4], dir; point_t constraint[2]; point_t cur; point_t off; int *pivk = NULL; /* pivk[n] */ int *nc = NULL; /* nc[n]: next corner */ point_t dk; /* direction of k-k1 */ int a, b, c, d; SAFE_MALLOC(pivk, n, int); SAFE_MALLOC(nc, n, int); /* initialize the nc data structure. Point from each point to the furthest future point to which it is connected by a vertical or horizontal segment. We take advantage of the fact that there is always a direction change at 0 (due to the path decomposition algorithm). But even if this were not so, there is no harm, as in practice, correctness does not depend on the word "furthest" above. */ k = 0; for (i=n-1; i>=0; i--) { if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) { k = i+1; /* necessarily i<n-1 in this case */ } nc[i] = k; } SAFE_MALLOC(pp->lon, n, int); /* determine pivot points: for each i, let pivk[i] be the furthest k such that all j with i<j<k lie on a line connecting i,k. */ for (i=n-1; i>=0; i--) { ct[0] = ct[1] = ct[2] = ct[3] = 0; /* keep track of "directions" that have occurred */ dir = (3+3*(pt[mod(i+1,n)].x-pt[i].x)+(pt[mod(i+1,n)].y-pt[i].y))/2; ct[dir]++; constraint[0].x = 0; constraint[0].y = 0; constraint[1].x = 0; constraint[1].y = 0; /* find the next k such that no straight line from i to k */ k = nc[i]; k1 = i; while (1) { dir = (3+3*sign(pt[k].x-pt[k1].x)+sign(pt[k].y-pt[k1].y))/2; ct[dir]++; /* if all four "directions" have occurred, cut this path */ if (ct[0] && ct[1] && ct[2] && ct[3]) { pivk[i] = k1; goto foundk; } cur.x = pt[k].x - pt[i].x; cur.y = pt[k].y - pt[i].y; /* see if current constraint is violated */ if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) { goto constraint_viol; } /* else, update constraint */ if (abs(cur.x) <= 1 && abs(cur.y) <= 1) { /* no constraint */ } else { off.x = cur.x + ((cur.y>=0 && (cur.y>0 || cur.x<0)) ? 1 : -1); off.y = cur.y + ((cur.x<=0 && (cur.x<0 || cur.y<0)) ? 1 : -1); if (xprod(constraint[0], off) >= 0) { constraint[0] = off; } off.x = cur.x + ((cur.y<=0 && (cur.y<0 || cur.x<0)) ? 1 : -1); off.y = cur.y + ((cur.x>=0 && (cur.x>0 || cur.y<0)) ? 1 : -1); if (xprod(constraint[1], off) <= 0) { constraint[1] = off; } } k1 = k; k = nc[k1]; if (!cyclic(k,i,k1)) { break; } } constraint_viol: /* k1 was the last "corner" satisfying the current constraint, and k is the first one violating it. We now need to find the last point along k1..k which satisfied the constraint. */ dk.x = sign(pt[k].x-pt[k1].x); dk.y = sign(pt[k].y-pt[k1].y); cur.x = pt[k1].x - pt[i].x; cur.y = pt[k1].y - pt[i].y; /* find largest integer j such that xprod(constraint[0], cur+j*dk) >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity of xprod. */ a = xprod(constraint[0], cur); b = xprod(constraint[0], dk); c = xprod(constraint[1], cur); d = xprod(constraint[1], dk); /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This can be solved with integer arithmetic. */ j = INFTY; if (b<0) { j = floordiv(a,-b); } if (d>0) { j = min(j, floordiv(-c,d)); } pivk[i] = mod(k1+j,n); foundk: ; } /* for i */ /* clean up: for each i, let lon[i] be the largest k such that for all i' with i<=i'<k, i'<k<=pivk[i']. */ j=pivk[n-1]; pp->lon[n-1]=j; for (i=n-2; i>=0; i--) { if (cyclic(i+1,pivk[i],j)) { j=pivk[i]; } pp->lon[i]=j; } for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) { pp->lon[i] = j; } free(pivk); free(nc); return 0; malloc_error: free(pivk); free(nc); return 1; }
/* Convert a string into day, month and year integers Convert a string into day / month / year integers according to the current dateFormat value. This function will always parse a single number as the day of the month, regardless of the ordering of the dateFormat value. Two numbers will always be parsed as the day and the month, in the same order that they appear in the dateFormat value. Three numbers are parsed exactly as specified in the dateFormat field. Fully formatted UTC timestamp strings are converted separately. param buff - pointer to date string param day - will store day of the month as 1 ... 31 param month - will store month of the year as 1 ... 12 param year - will store the year (4-digit) return TRUE if date appeared to be valid. Globals: global dateFormat value */ static gboolean qof_scan_date_internal (const char *buff, int *day, int *month, int *year, QofDateFormat which_format) { char *dupe, *tmp, *first_field, *second_field, *third_field; int iday, imonth, iyear; int now_day, now_month, now_year; struct tm *now, utc; time64 secs; if (!buff) return(FALSE); if (which_format == QOF_DATE_FORMAT_UTC) { if (strptime(buff, QOF_UTC_DATE_FORMAT, &utc) || strptime (buff, "%Y-%m-%d", &utc)) { *day = utc.tm_mday; *month = utc.tm_mon + 1; *year = utc.tm_year + 1900; return TRUE; } else { return FALSE; } } dupe = g_strdup (buff); tmp = dupe; first_field = NULL; second_field = NULL; third_field = NULL; /* Use strtok to find delimiters */ if (tmp) { static const char *delims = ".,-+/\\()년월年月 "; first_field = strtok (tmp, delims); if (first_field) { second_field = strtok (NULL, delims); if (second_field) { third_field = strtok (NULL, delims); } } } /* today's date */ gnc_time (&secs); now = gnc_localtime (&secs); now_day = now->tm_mday; now_month = now->tm_mon + 1; now_year = now->tm_year + 1900; gnc_tm_free (now); /* set defaults: if day or month appear to be blank, use today's date */ iday = now_day; imonth = now_month; iyear = -1; /* get numeric values */ switch (which_format) { case QOF_DATE_FORMAT_LOCALE: if (buff[0] != '\0') { struct tm thetime; gchar *format = g_strdup (GNC_D_FMT); gchar *stripped_format = g_strdup (GNC_D_FMT); gint counter = 0, stripped_counter = 0; /* strptime can't handle the - format modifier * let's strip it out of the format before using it */ while (format[counter] != '\0') { stripped_format[stripped_counter] = format[counter]; if ((format[counter] == '%') && (format[counter+1] == '-')) counter++; // skip - format modifier counter++; stripped_counter++; } stripped_format[stripped_counter] = '\0'; g_free (format); /* Parse time string. */ memset(&thetime, -1, sizeof(struct tm)); strptime (buff, stripped_format, &thetime); g_free (stripped_format); if (third_field) { /* Easy. All three values were parsed. */ iyear = thetime.tm_year + 1900; iday = thetime.tm_mday; imonth = thetime.tm_mon + 1; } else if (second_field) { /* Hard. Two values parsed. Figure out the ordering. */ if (thetime.tm_year == -1) { /* %m-%d or %d-%m. Don't care. Already parsed correctly. */ iday = thetime.tm_mday; imonth = thetime.tm_mon + 1; } else if (thetime.tm_mon != -1) { /* Must be %Y-%m-%d. Reparse as %m-%d.*/ imonth = atoi(first_field); iday = atoi(second_field); } else { /* Must be %Y-%d-%m. Reparse as %d-%m. */ iday = atoi(first_field); imonth = atoi(second_field); } } else if (first_field) { iday = atoi(first_field); } } break; case QOF_DATE_FORMAT_UK: case QOF_DATE_FORMAT_CE: if (third_field) { iday = atoi(first_field); imonth = atoi(second_field); iyear = atoi(third_field); } else if (second_field) { iday = atoi(first_field); imonth = atoi(second_field); } else if (first_field) { iday = atoi(first_field); } break; case QOF_DATE_FORMAT_ISO: if (third_field) { iyear = atoi(first_field); imonth = atoi(second_field); iday = atoi(third_field); } else if (second_field) { imonth = atoi(first_field); iday = atoi(second_field); } else if (first_field) { iday = atoi(first_field); } break; case QOF_DATE_FORMAT_US: default: if (third_field) { imonth = atoi(first_field); iday = atoi(second_field); iyear = atoi(third_field); } else if (second_field) { imonth = atoi(first_field); iday = atoi(second_field); } else if (first_field) { iday = atoi(first_field); } break; } g_free (dupe); if ((12 < imonth) || (31 < iday)) { /* * Ack! Thppfft! Someone just fed this routine a string in the * wrong date format. This is known to happen if a register * window is open when changing the date format. Try the * previous date format. If that doesn't work, see if we can * exchange month and day. If that still doesn't work, * bail and give the caller what they asked for (garbage) * parsed in the new format. * * Note: This test cannot detect any format change that only * swaps month and day field, if the day is 12 or less. This is * deemed acceptable given the obscurity of this bug. */ if ((which_format != prevQofDateFormat) && qof_scan_date_internal(buff, day, month, year, prevQofDateFormat)) { return(TRUE); } if ((12 < imonth) && (12 >= iday)) { int tmp = imonth; imonth = iday; iday = tmp; } else { return FALSE; } } /* if no year was entered, choose a year according to the dateCompletion preference. If it is QOF_DATE_COMPLETION_THISYEAR, use the current year, else if it is QOF_DATE_COMPLETION_SLIDING, use a sliding window that starts dateCompletionBackMonths before the current month. We go by whole months, rather than days, because presumably this is less confusing. */ if (iyear == -1) { if (dateCompletion == QOF_DATE_COMPLETION_THISYEAR) { iyear = now_year; /* use the current year */ } else { iyear = now_year - floordiv(imonth - now_month + dateCompletionBackMonths, 12); } } /* If the year entered is smaller than 100, assume we mean the current century (and are not revising some roman emperor's books) */ if (iyear < 100) iyear += ((int) ((now_year + 50 - iyear) / 100)) * 100; if (year) *year = iyear; if (month) *month = imonth; if (day) *day = iday; return(TRUE); }
//************ FROM MONTHLY *************** static void MtoD_ym(npy_int64 ordinal, int *y, int *m) { *y = floordiv(ordinal, 12) + BASE_YEAR; *m = mod_compat(ordinal, 12) + 1; }