size_t qof_print_date_buff (char * buff, size_t len, time64 t) { if (!buff) return 0; GncDateTime gncdt(t); std::string str = gncdt.format(qof_date_format_get_string(dateFormat)); strncpy(buff, str.c_str(), len); if (str.length() >= len) buff[len - 1] = '\0'; return strlen(buff); }
size_t qof_print_date_dmy_buff (char * buff, size_t len, int day, int month, int year) { if (!buff) return 0; GncDate date(year, month, day); std::string str = date.format(qof_date_format_get_string(dateFormat)); strncpy(buff, str.c_str(), len); if (str.length() >= len) buff[len - 1] = '\0'; return strlen(buff); }
//! \brief helper function // Try to make a valid tm using the user set date format. Return false if it fails. gboolean isDateValid(char * date_string) { char *tmp; const gchar* date_format_string = qof_date_format_get_string (qof_date_format_get()); // Get the user set date format string struct tm time_struct; memset(&time_struct, 0, sizeof(struct tm)); tmp = strptime(date_string, date_format_string, &time_struct); if (tmp == NULL) return FALSE; return TRUE; }
/* Return the field separator for the current date format return date character */ char dateSeparator (void) { static char locale_separator = '\0'; switch (dateFormat) { case QOF_DATE_FORMAT_CE: return '.'; case QOF_DATE_FORMAT_ISO: case QOF_DATE_FORMAT_UTC: return '-'; case QOF_DATE_FORMAT_US: case QOF_DATE_FORMAT_UK: default: return '/'; case QOF_DATE_FORMAT_LOCALE: if (locale_separator != '\0') return locale_separator; else { /* Make a guess */ gchar string[256]; struct tm tm; time64 secs; gchar *s; secs = gnc_time (NULL); gnc_localtime_r(&secs, &tm); auto normalized_fmt = normalize_format(qof_date_format_get_string(dateFormat)); qof_strftime(string, sizeof(string), normalized_fmt.c_str(), &tm); for (s = string; *s != '\0'; s++) if (!isdigit(*s)) return (locale_separator = *s); } break; } return '\0'; }
size_t qof_print_date_buff (char * buff, size_t len, time64 t) { if (!buff) return 0; try { GncDateTime gncdt(t); std::string str = gncdt.format(qof_date_format_get_string(dateFormat)); strncpy(buff, str.c_str(), len); if (str.length() >= len) buff[len - 1] = '\0'; } catch(std::logic_error& err) { PWARN("Error processing time64 %" PRId64 ": %s", t, err.what()); } catch(std::runtime_error& err) { PWARN("Error processing time64 %" PRId64 ": %s", t, err.what()); } return strlen(buff); }
/* qof_date_format_get_string get the date format string for the current format returns: string Globals: dateFormat */ const gchar *qof_date_format_get_string(QofDateFormat df) { switch (df) { case QOF_DATE_FORMAT_US: return "%m/%d/%Y"; case QOF_DATE_FORMAT_UK: return "%d/%m/%Y"; case QOF_DATE_FORMAT_CE: return "%d.%m.%Y"; case QOF_DATE_FORMAT_UTC: return "%Y-%m-%dT%H:%M:%SZ"; case QOF_DATE_FORMAT_ISO: return "%Y-%m-%d"; case QOF_DATE_FORMAT_UNSET: // use global return qof_date_format_get_string (dateFormat); case QOF_DATE_FORMAT_LOCALE: default: break; }; return GNC_D_FMT; }
size_t qof_print_date_dmy_buff (char * buff, size_t len, int day, int month, int year) { if (!buff) return 0; try { GncDate date(year, month, day); std::string str = date.format(qof_date_format_get_string(dateFormat)); strncpy(buff, str.c_str(), len); if (str.length() >= len) buff[len - 1] = '\0'; } catch(std::logic_error& err) { PWARN("Error processing year-month-day %d-%d-%d: %s", year, month, day, err.what()); } catch(std::runtime_error& err) { PWARN("Error processing year-month-day %d-%d-%d: %s", year, month, day, err.what()); } return strlen(buff); }
void gnc_date_format_refresh (GNCDateFormat *gdf) { GNCDateFormatPriv *priv; int sel_option; gboolean enable_year, enable_month, enable_custom, check_modifiers; static gchar *format, *c; gchar date_string[MAX_DATE_LEN]; time64 secs_now; struct tm today; g_return_if_fail(gdf); g_return_if_fail(GNC_IS_DATE_FORMAT(gdf)); priv = GNC_DATE_FORMAT_GET_PRIVATE(gdf); sel_option = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->format_combobox)); switch (sel_option) { case QOF_DATE_FORMAT_CUSTOM: format = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->custom_entry))); enable_year = enable_month = check_modifiers = FALSE; enable_custom = TRUE; break; case QOF_DATE_FORMAT_LOCALE: case QOF_DATE_FORMAT_UTC: format = g_strdup(qof_date_format_get_string(sel_option)); enable_year = enable_month = check_modifiers = enable_custom = FALSE; break; case QOF_DATE_FORMAT_ISO: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->months_number), TRUE); enable_year = check_modifiers = TRUE; enable_month = enable_custom = FALSE; break; default: enable_year = enable_month = check_modifiers = TRUE; enable_custom = FALSE; break; } /* Tweak widget sensitivities, as appropriate. */ gnc_date_format_enable_year(gdf, enable_year); gnc_date_format_enable_month(gdf, enable_month); gnc_date_format_enable_format(gdf, enable_custom); /* Update the format string based upon the user's preferences */ if (check_modifiers) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->months_number))) { format = g_strdup(qof_date_format_get_string(sel_option)); } else { format = g_strdup(qof_date_text_format_get_string(sel_option)); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->months_name))) { c = strchr(format, 'b'); if (c) *c = 'B'; } } if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->years_button))) { c = strchr(format, 'y'); if (c) *c = 'Y'; } } /* * Give feedback on the format string so users can see how it works * without having to read the strftime man page. Prevent recursive * signals. */ g_signal_handlers_block_matched(priv->custom_entry, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, gdf); gtk_entry_set_text(GTK_ENTRY(priv->custom_entry), format); g_signal_handlers_unblock_matched(priv->custom_entry, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, gdf); /* Visual feedback on what the date will look like. */ secs_now = gnc_time (NULL); gnc_localtime_r (&secs_now, &today); qof_strftime(date_string, MAX_DATE_LEN, format, &today); gtk_label_set_text(GTK_LABEL(priv->sample_label), date_string); g_free(format); }
//! \brief try to fix some common errors in the csv representation of invoices //! * corrects the date format //! * corrects ambigous values in multi line invoices //! * ensures customer exists //! * if quantity is unset, set to 1 //! * if price is unset, delete row void gnc_bi_import_fix_bis (GtkListStore * store, guint * fixed, guint * deleted, GString * info, gchar *type) { GtkTreeIter iter; gboolean valid, row_deleted, row_fixed; gchar *id, *date_opened, *date_posted, *due_date, *owner_id, *date, *quantity, *price; GString *prev_id, *prev_date_opened, *prev_date_posted, *prev_owner_id, *prev_date; // needed to fix multi line invoices guint dummy; gint row = 1; const gchar* date_format_string = qof_date_format_get_string (qof_date_format_get()); // Get the user set date format string //date_format_string = qof_date_format_get_string (qof_date_format_get()); DEBUG("date_format_string: %s",date_format_string); // allow the call to this function with only GtkListeStore* specified if (!fixed) fixed = &dummy; if (!deleted) deleted = &dummy; *fixed = 0; *deleted = 0; // init strings prev_id = g_string_new (""); prev_date_opened = g_string_new (""); prev_date_posted = g_string_new (""); prev_owner_id = g_string_new (""); prev_date = g_string_new (""); valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); while (valid) { row_deleted = FALSE; row_fixed = FALSE; // Walk through the list, reading each row gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, ID, &id, DATE_OPENED, &date_opened, DATE_POSTED, &date_posted, DUE_DATE, &due_date, OWNER_ID, &owner_id, DATE, &date, QUANTITY, &quantity, PRICE, &price, -1); if (strlen (price) == 0) { // invalid row (no price given) // no fix possible -> delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, PRICE_NOT_SET: id=%s\n"), row, id); } // TODO: QTY get set to 1 later if field is empty. Delete this section? else if (strlen (quantity) == 0) { // invalid row (no quantity given) // no fix possible -> delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, QTY_NOT_SET: id=%s\n"), row, id); } else { // TODO: If id is empty get the next one in the series. Bug 731105 if (strlen (id) == 0) { // no invoice id specified if (prev_id->len == 0) { // cannot fix -> delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, ID_NOT_SET\n"), row); } else { // this is a fixable multi line invoice gtk_list_store_set (store, &iter, ID, prev_id->str, -1); row_fixed = TRUE; } } else { // remember invoice id (to be able to fix multi line invoices) g_string_assign (prev_id, id); // new invoice => reset all other fixable entries g_string_assign (prev_date_opened, ""); g_string_assign (prev_date_posted, ""); g_string_assign (prev_owner_id, ""); g_string_assign (prev_date, ""); } } if (!row_deleted) { // the row is valid (price and id are valid) if(!isDateValid(date_opened)) { if (prev_date_opened->len == 0) { // fix this by using the current date gchar temp[20]; GDate date; g_date_clear (&date, 1); gnc_gdate_set_today (&date); g_date_strftime (temp, 20, date_format_string, &date); // Create a user specified date string. g_string_assign (prev_date_opened, temp); } // fix this by using the previous date_opened value (multi line invoice) gtk_list_store_set (store, &iter, DATE_OPENED, prev_date_opened->str, -1); row_fixed = TRUE; } else { // remember date_opened (to be able to fix multi line invoices) g_string_assign (prev_date_opened, date_opened); } // date_opened is valid if(!isDateValid(date_posted)) { if (prev_date_posted->len == 0) { // this invoice will have to get posted manually } else { // multi line invoice => fix it gtk_list_store_set (store, &iter, DATE_POSTED, prev_date_posted->str, -1); row_fixed = TRUE; } } else { // remember date_opened (to be able to fix multi line invoices) g_string_assign (prev_date_posted, date_posted); } // date_posted is valid /* // Check if due date is valid. Set it to date_posted if not valid or missing. if(!isDateValid(due_date)) { gtk_list_store_set (store, &iter, DUE_DATE, date_posted, -1); row_fixed = TRUE; } // due_date is valid */ if (strlen (quantity) == 0) { // quantity is unset => set to 1 gtk_list_store_set (store, &iter, QUANTITY, "1", -1); row_fixed = TRUE; } // quantity is valid if (strlen (owner_id) == 0) { if (prev_owner_id->len == 0) { // no customer given and not fixable => delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, OWNER_NOT_SET: id=%s\n"), row, id); } else { gtk_list_store_set (store, &iter, owner_id, prev_owner_id->str, -1); row_fixed = TRUE; } } else { // remember owner_id g_string_assign (prev_owner_id, owner_id); } if (g_ascii_strcasecmp (type, "BILL") == 0) { // BILL: check, if vendor exists if (!gnc_search_vendor_on_id (gnc_get_current_book (), prev_owner_id->str)) { // vendor not found => delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, VENDOR_DOES_NOT_EXIST: id=%s\n"), row, id); } } else if (g_ascii_strcasecmp (type, "INVOICE") == 0) { // INVOICE: check, if customer exists if (!gnc_search_customer_on_id (gnc_get_current_book (), prev_owner_id->str)) { // customer not found => delete row valid = gtk_list_store_remove (store, &iter); row_deleted = TRUE; g_string_append_printf (info, _("ROW %d DELETED, CUSTOMER_DOES_NOT_EXIST: id=%s\n"), row, id); } } // owner_id is valid } g_free (id); g_free (date_opened); g_free (date_posted); g_free (owner_id); g_free (date); g_free (quantity); g_free (price); if (row_deleted) { (*deleted)++; // reset all remembered values g_string_assign (prev_id, ""); g_string_assign (prev_date_opened, ""); g_string_assign (prev_date_posted, ""); g_string_assign (prev_owner_id, ""); g_string_assign (prev_date, ""); } else if (row_fixed) (*fixed)++; if (!row_deleted) valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); row++; } // deallocate strings g_string_free (prev_id, TRUE); g_string_free (prev_date_opened, TRUE); g_string_free (prev_date_posted, TRUE); g_string_free (prev_owner_id, TRUE); g_string_free (prev_date, TRUE); if (info && (info->len > 0)) { g_string_prepend (info, "\n\n"); g_string_prepend (info, _("These rows were deleted:")); } }