Example #1
0
struct tm*
gnc_localtime (const time64 *secs)
{
    auto time = static_cast<struct tm*>(calloc(1, sizeof(struct tm)));
    if (gnc_localtime_r (secs, time) == NULL)
    {
        gnc_tm_free (time);
        return NULL;
    }
    return time;
}
Example #2
0
struct tm*
gnc_localtime (const time64 *secs)
{
     struct tm *time = g_slice_alloc0 (sizeof (struct tm));
     if (gnc_localtime_r (secs, time) == NULL)
     {
	  gnc_tm_free (time);
	  return NULL;
     }
     return time;
}
/* This function converts a time64 value date to separate entities */
gboolean
gcrd_time2dmy (time64 raw_time, gint *day, gint *month, gint *year)
{
    struct tm * timeinfo;
  
    timeinfo = gnc_localtime (&raw_time);
 
    *day = timeinfo->tm_mday;
    *month = timeinfo->tm_mon + 1;
    *year = timeinfo->tm_year + 1900;
    gnc_tm_free (timeinfo);
    return TRUE;
}
Example #4
0
static void
gnc_date_edit_set_time_internal (GNCDateEdit *gde, time64 the_time)
{
    char buffer [40];
    struct tm *mytm = gnc_localtime (&the_time);

    g_return_if_fail(mytm != NULL);

    /* Update the date text. */
    qof_print_date_dmy_buff(buffer, 40,
                            mytm->tm_mday,
                            mytm->tm_mon + 1,
                            1900 + mytm->tm_year);
    gtk_entry_set_text(GTK_ENTRY(gde->date_entry), buffer);

    /* Update the calendar. */
    if (!gde->in_selected_handler)
    {
	gtk_calendar_select_day(GTK_CALENDAR (gde->calendar), 1);
	gtk_calendar_select_month(GTK_CALENDAR (gde->calendar),
				  mytm->tm_mon, 1900 + mytm->tm_year);
	gtk_calendar_select_day(GTK_CALENDAR (gde->calendar), mytm->tm_mday);
    }

    /* Set the time of day. */
    if (gde->flags & GNC_DATE_EDIT_24_HR)
        qof_strftime (buffer, sizeof (buffer), "%H:%M", mytm);
    else
        qof_strftime (buffer, sizeof (buffer), "%I:%M %p", mytm);
    gtk_entry_set_text(GTK_ENTRY(gde->time_entry), buffer);

    gnc_tm_free (mytm);

    g_signal_emit (gde, date_edit_signals [DATE_CHANGED], 0);
    g_signal_emit (gde, date_edit_signals [TIME_CHANGED], 0);
}
Example #5
0
/* 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);
}
Example #6
0
/* parse_date
time64 parse_date (const char* date_str, int format)// C: 14 in 7 SCM: 9 in 2 Local: 1:0:0
*/
static void
test_parse_date (void)
{
    time64 rawtime = gnc_time (NULL);
    struct tm *tm = gnc_gmtime (&rawtime);
    int curr_year = tm->tm_year;


    /* Note: tm_year = year - 1900 and tm_mon = 0-11
     * I'm writing the expected values as subtractions for easier
     * comparison with the date string under test
     */
    parse_date_data test_dates[] =
    {
        // supported combinations  -/.'
        { 0, "2013-08-01", 2013 - 1900,  8 - 1,  1},
        { 0,  "2013-8-01", 2013 - 1900,  8 - 1,  1},
        { 0,  "2013-08-1", 2013 - 1900,  8 - 1,  1},
        { 0,   "2013-8-1", 2013 - 1900,  8 - 1,  1},
        { 0,   "13-08-01", 2013 - 1900,  8 - 1,  1},
        { 0,    "13-8-01", 2013 - 1900,  8 - 1,  1},
        { 0,    "13-08-1", 2013 - 1900,  8 - 1,  1},
        { 0,     "13-8-1", 2013 - 1900,  8 - 1,  1},
        { 0, "2009/11/04", 2009 - 1900, 11 - 1,  4},
        { 0,  "1985.3.12", 1985 - 1900,  3 - 1, 12},
        { 0,      "3'6'8", 2003 - 1900,  6 - 1,  8},
        { 0,   "20130801", 2013 - 1900,  8 - 1,  1},
        { 1, "01-08-2013", 2013 - 1900,  8 - 1,  1},
        { 1,  "01-8-2013", 2013 - 1900,  8 - 1,  1},
        { 1,  "1-08-2013", 2013 - 1900,  8 - 1,  1},
        { 1,   "1-8-2013", 2013 - 1900,  8 - 1,  1},
        { 1,   "01-08-13", 2013 - 1900,  8 - 1,  1},
        { 1,    "01-8-13", 2013 - 1900,  8 - 1,  1},
        { 1,    "1-08-13", 2013 - 1900,  8 - 1,  1},
        { 1,     "1-8-13", 2013 - 1900,  8 - 1,  1},
        { 1, "04/11/2009", 2009 - 1900, 11 - 1,  4},
        { 1,  "12.3.1985", 1985 - 1900,  3 - 1, 12},
        { 1,      "8'6'3", 2003 - 1900,  6 - 1,  8},
        { 1,   "01082013", 2013 - 1900,  8 - 1,  1},
        { 2, "08-01-2013", 2013 - 1900,  8 - 1,  1},
        { 2,  "8-01-2013", 2013 - 1900,  8 - 1,  1},
        { 2,  "08-1-2013", 2013 - 1900,  8 - 1,  1},
        { 2,   "8-1-2013", 2013 - 1900,  8 - 1,  1},
        { 2,   "08-01-13", 2013 - 1900,  8 - 1,  1},
        { 2,    "8-01-13", 2013 - 1900,  8 - 1,  1},
        { 2,    "08-1-13", 2013 - 1900,  8 - 1,  1},
        { 2,     "8-1-13", 2013 - 1900,  8 - 1,  1},
        { 2, "11/04/2009", 2009 - 1900, 11 - 1,  4},
        { 2,  "3.12.1985", 1985 - 1900,  3 - 1, 12},
        { 2,      "6'8'3", 2003 - 1900,  6 - 1,  8},
        { 2,   "08012013", 2013 - 1900,  8 - 1,  1},
        { 3,      "01-08",   curr_year,  8 - 1,  1},
        { 3,       "01-8",   curr_year,  8 - 1,  1},
        { 3,       "1-08",   curr_year,  8 - 1,  1},
        { 3,        "1-8",   curr_year,  8 - 1,  1},
        { 3,      "04/11",   curr_year, 11 - 1,  4},
        { 3,       "12.3",   curr_year,  3 - 1, 12},
        { 3,        "8'6",   curr_year,  6 - 1,  8},
        { 4,      "08-01",   curr_year,  8 - 1,  1},
        { 4,       "8-01",   curr_year,  8 - 1,  1},
        { 4,       "08-1",   curr_year,  8 - 1,  1},
        { 4,        "8-1",   curr_year,  8 - 1,  1},
        { 4,      "11/04",   curr_year, 11 - 1,  4},
        { 4,       "3.12",   curr_year,  3 - 1, 12},
        { 4,        "6'8",   curr_year,  6 - 1,  8},

        // ambiguous date formats
        // current parser doesn't know how to disambiguate
        // and hence refuses to parse
        // can possibly improved with a smarter parser
        { 0,     "130801",          -1,     -1, -1},
        { 1,     "010813",          -1,     -1, -1},
        { 2,     "080113",          -1,     -1, -1},
        { 3,       "0108",          -1,     -1, -1},
        { 4,       "0801",          -1,     -1, -1},

        // Combinations that don't make sense
        // but can still be entered by a user
        // Should ideally all result in refusal to parse...
        { 0,      "08-01",          -1,     -1, -1},
        { 0,       "0801",          -1,     -1, -1},
        { 1,      "01-08",          -1,     -1, -1},
        { 1,       "0108",          -1,     -1, -1},
        { 2,      "08-01",          -1,     -1, -1},
        { 2,       "0801",          -1,     -1, -1},
        { 3, "01-08-2013",   curr_year,  8 - 1,  1}, // BAD behavior !
        { 3,   "01-08-13",   curr_year,  8 - 1,  1}, // BAD behavior !
        { 3,   "08-08-08",   curr_year,  8 - 1,  8}, // BAD behavior !
        { 3,   "01082013",          -1,     -1, -1},
        { 3,     "010813",          -1,     -1, -1},
        { 3,   "20130108",          -1,     -1, -1},
        { 4, "08-01-2013",   curr_year,  8 - 1,  1}, // BAD behavior !
        { 4,   "08-01-13",   curr_year,  8 - 1,  1}, // BAD behavior !
        { 4, "2013-08-01",          -1,     -1, -1},
        { 4,   "09-08-01",   curr_year,  9 - 1,  8}, // BAD behavior !
        { 4,   "08012013",          -1,     -1, -1},
        { 4,     "080113",          -1,     -1, -1},
        { 4,   "20130801",          -1,     -1, -1},

        // Sentinel to mark the end of available tests
        { 0,         NULL,           0,      0,  0},

    };
    int i = 0;

    gnc_tm_free(tm);
    while (test_dates[i].date_str)
    {
        gboolean success = TRUE;
        int got_year = 0, got_month = 0, got_day = 0;

        rawtime = parse_date (test_dates[i].date_str, test_dates[i].date_fmt);
        if (rawtime == -1)
            got_year = got_month = got_day = -1;
        else
        {
            tm = gnc_gmtime (&rawtime);
            got_year = tm->tm_year;
            got_month = tm->tm_mon;
            got_day = tm->tm_mday;
            gnc_tm_free(tm);
        }

        if ((got_year  != test_dates[i].exp_year) ||
            (got_month != test_dates[i].exp_month) ||
            (got_day   != test_dates[i].exp_day))
        {
            g_error ("Parse_date failed for date '%s' and format '%d'.\n"
                            "Expected result: year %d, month %d, day %d\n"
                            "Obtained result: year %d, month %d, day %d",
                            test_dates[i].date_str,
                            test_dates[i].date_fmt,
                            test_dates[i].exp_year,
                            test_dates[i].exp_month,
                            test_dates[i].exp_day,
                            got_year, got_month, got_day);
        }

        i++;
    }


}