/* nth_weekday_compare() is a helper function for the PERIOD_{NTH,LAST}_WEEKDAY case. It returns the offset, in days, from 'next' to the nth weekday specified by the 'start' date (and the period type), in the same month as 'next'. A negative offset means earlier than 'next'; a zero offset means 'next' *is* the nth weekday in that month; a positive offset means later than 'next'. */ static gint nth_weekday_compare(const GDate *start, const GDate *next, PeriodType pt) { GDateDay sd, nd; gint matchday, dim, week; nd = g_date_get_day(next); sd = g_date_get_day(start); week = sd / 7 > 3 ? 3 : sd / 7; if (week > 0 && sd % 7 == 0 && sd != 28) --week; /* matchday has a week part, capped at 3 weeks, and a day part, capped at 7 days, so max(matchday) == 3*7 + 7 == 28. */ matchday = 7 * week + //((sd - 1) / 7 == 4 ? 3 : (sd - 1) / 7) + (nd - g_date_get_weekday(next) + g_date_get_weekday(start) + 7) % 7; /* That " + 7" is to avoid negative modulo in case nd < 6. */ dim = g_date_get_days_in_month( g_date_get_month(next), g_date_get_year(next)); if ((dim - matchday) >= 7 && pt == PERIOD_LAST_WEEKDAY) matchday += 7; /* Go to the fifth week, if needed */ if (pt == PERIOD_NTH_WEEKDAY && (matchday % 7 == 0)) matchday += 7; return matchday - nd; /* Offset from 'next' to matchday */ }
static void _monthly_append_when(Recurrence *r, GString *buf) { GDate date = recurrenceGetDate(r); if (recurrenceGetPeriodType(r) == PERIOD_LAST_WEEKDAY) { gchar day_name_buf[abbrev_day_name_bufsize]; gnc_dow_abbrev(day_name_buf, abbrev_day_name_bufsize, g_date_get_weekday(&date) % 7); /* translators: %s is an already-localized form of the day of the week. */ g_string_append_printf(buf, _("last %s"), day_name_buf); } else if (recurrenceGetPeriodType(r) == PERIOD_NTH_WEEKDAY) { int week = 0; int day_of_month_index = 0; const char *numerals[] = {N_("1st"), N_("2nd"), N_("3rd"), N_("4th")}; gchar day_name_buf[abbrev_day_name_bufsize]; gnc_dow_abbrev(day_name_buf, abbrev_day_name_bufsize, g_date_get_weekday(&date) % 7); day_of_month_index = g_date_get_day(&date) - 1; week = day_of_month_index / 7 > 3 ? 3 : day_of_month_index / 7; if (week > 0 && day_of_month_index % 7 == 0) --week; /* translators: %s is the string 1st, 2nd, 3rd and so on, and * %s is an already-localized form of the day of the week. */ g_string_append_printf(buf, _("%s %s"), _(numerals[week]), day_name_buf); } else { /* translators: %u is the day of month */ g_string_append_printf(buf, "%u", g_date_get_day(&date)); } }
static int _get_monthly_combobox_index(Recurrence *r) { GDate recurrence_date = recurrenceGetDate(r); int week = 0; int day_of_month_index = g_date_get_day(&recurrence_date) - 1; if (recurrenceGetPeriodType(r) == PERIOD_END_OF_MONTH) { day_of_month_index = LAST_DAY_OF_MONTH_OPTION_INDEX; } else if (recurrenceGetPeriodType(r) == PERIOD_LAST_WEEKDAY) { day_of_month_index = LAST_DAY_OF_MONTH_OPTION_INDEX + g_date_get_weekday(&recurrence_date); } else if (recurrenceGetPeriodType(r) == PERIOD_NTH_WEEKDAY) { week = day_of_month_index / 7 > 3 ? 3 : day_of_month_index / 7; if (week > 0 && day_of_month_index % 7 == 0) --week; day_of_month_index = LAST_DAY_OF_MONTH_OPTION_INDEX + 7 + g_date_get_weekday(&recurrence_date) + 7 * week; } /* else { default value } */ return day_of_month_index; }
static Recurrence* _get_day_of_month_recurrence(GncFrequency *gf, GDate *start_date, int multiplier, char *combo_name, char *combo_weekend_name) { Recurrence *r; GtkWidget *day_of_month_combo = glade_xml_get_widget(gf->gxml, combo_name); int day_of_month_index = gtk_combo_box_get_active(GTK_COMBO_BOX(day_of_month_combo)); GtkWidget *weekend_adjust_combo = glade_xml_get_widget(gf->gxml, combo_weekend_name); int weekend_adjust = gtk_combo_box_get_active(GTK_COMBO_BOX(weekend_adjust_combo)); GDateWeekday selected_day_of_week; GDate *day_of_week_date; int selected_index, selected_week; r = g_new0(Recurrence, 1); if (day_of_month_index > LAST_DAY_OF_MONTH_OPTION_INDEX + 7) { selected_index = day_of_month_index - LAST_DAY_OF_MONTH_OPTION_INDEX - 7; day_of_week_date = g_date_new_julian(g_date_get_julian(start_date)); selected_week = (selected_index - 1) / 7 == 4 ? 3 : (selected_index - 1) / 7; selected_day_of_week = selected_index - 7 * selected_week; g_date_set_day(day_of_week_date, 1); while (g_date_get_weekday(day_of_week_date) != selected_day_of_week) g_date_add_days(day_of_week_date, 1); g_date_add_days(day_of_week_date, 7 * selected_week); recurrenceSet(r, multiplier, PERIOD_NTH_WEEKDAY, day_of_week_date, WEEKEND_ADJ_NONE); } else if (day_of_month_index > LAST_DAY_OF_MONTH_OPTION_INDEX) { day_of_week_date = g_date_new_julian(g_date_get_julian(start_date)); selected_day_of_week = day_of_month_index - LAST_DAY_OF_MONTH_OPTION_INDEX; // increment until we align on the DOW, but stay inside the month g_date_set_day(day_of_week_date, 1); while (g_date_get_weekday(day_of_week_date) != selected_day_of_week) g_date_add_days(day_of_week_date, 1); recurrenceSet(r, multiplier, PERIOD_LAST_WEEKDAY, day_of_week_date, weekend_adjust); } else if (day_of_month_index == LAST_DAY_OF_MONTH_OPTION_INDEX) { GDate *day_of_month = g_date_new_julian(g_date_get_julian(start_date)); recurrenceSet(r, multiplier, PERIOD_END_OF_MONTH, day_of_month, weekend_adjust); } else { int allowable_date = -1; GDate *day_of_month = g_date_new_julian(g_date_get_julian(start_date)); allowable_date = MIN(day_of_month_index + 1, g_date_get_days_in_month(g_date_get_month(day_of_month), g_date_get_year(day_of_month))); g_date_set_day(day_of_month, allowable_date); recurrenceSet(r, multiplier, PERIOD_MONTH, day_of_month, weekend_adjust); } return r; }
guint utl_get_weekend_days_in_month_my (guint month, guint year) { GDate *tmpdate = NULL; guint i, day, days, weekend_days; g_return_val_if_fail (g_date_valid_dmy (1, month, year) == TRUE, 0); tmpdate = g_date_new_dmy (1, month, year); g_return_val_if_fail (tmpdate != NULL, 0); days = utl_date_get_days_in_month (tmpdate); weekend_days = 0; for (i = 1; i <= days; i++) { g_date_set_day (tmpdate, i); day = g_date_get_weekday (tmpdate); if (day == G_DATE_SATURDAY || day == G_DATE_SUNDAY) { weekend_days++; } } g_date_free (tmpdate); return weekend_days; }
const char* darxen_conversions_format_date_time(GDate *date, int seconds) { int intWeekday; int intMonth; intWeekday = g_date_get_weekday(date) - 1; intMonth = g_date_get_month(date) - 1; if (chrDateTime) g_free(chrDateTime); chrDateTime = g_new0(char, 26); sprintf(chrDateTime, "%s %02i:%02i:%02iZ %i-%s-%i", chrDays[intWeekday], darxen_conversions_time_get_hours(seconds), darxen_conversions_time_get_minutes(seconds), darxen_conversions_time_get_seconds(seconds), g_date_get_day(date), chrMonths[intMonth], g_date_get_year(date) ); return chrDateTime; }
void hippo_platform_impl_windows_migrate_cookie(const char *from_web_host, const char *to_web_host) { char *username; char *password; // See if we already have a cookie from the new host if (read_ie_login_cookie(to_web_host, &username, &password)) { g_free(username); g_free(password); return; } if (!read_ie_login_cookie(from_web_host, &username, &password)) return; GDate *date = g_date_new(); GTimeVal timeval; g_get_current_time(&timeval); g_date_set_time_val(date, &timeval); g_date_add_days(date, 5 * 365); // 5 years, more or less // Can't use g_date_strftime, since that would be unpredictably located // while we need fixed english-locale DAY, DD-MMM-YYYY HH:MM:SS GMT static const char *days[] = { "Mon", "Tue", "Wed", "The", "Fri", "Sat", "Sun" }; static const char * const months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; char *cookieUTF8 = g_strdup_printf("auth=host=%s&name=%s&password=%s; Path=/; expires = %s, %02d-%s-%04d 00:00:00 GMT", to_web_host, username, password, days[(int)g_date_get_weekday(date) - 1], g_date_get_day(date), months[(int)g_date_get_month(date) - 1], g_date_get_year(date)); g_date_free(date); HippoBSTR cookie; cookie.setUTF8(cookieUTF8, -1); g_free(cookieUTF8); HippoBSTR authUrl; makeAuthUrl(to_web_host, &authUrl); InternetSetCookie(authUrl, NULL, cookie); g_free(username); g_free(password); }
guint8 g_date_get_sunday_weeks_in_year (GDateYear year) { GDate d; g_return_val_if_fail (g_date_valid_year (year), 0); g_date_clear (&d, 1); g_date_set_dmy (&d, 1, 1, year); if (g_date_get_weekday (&d) == G_DATE_SUNDAY) return 53; g_date_set_dmy (&d, 31, 12, year); if (g_date_get_weekday (&d) == G_DATE_SUNDAY) return 53; if (g_date_is_leap_year (year)) { g_date_set_dmy (&d, 2, 1, year); if (g_date_get_weekday (&d) == G_DATE_SUNDAY) return 53; g_date_set_dmy (&d, 30, 12, year); if (g_date_get_weekday (&d) == G_DATE_SUNDAY) return 53; } return 52; }
/** * mrp_time_day_of_week: * @t: an #mrptime value * * Retrieves the day of week of the specified time. * * Return value: The day of week, in the range 0 to 6, where Sunday is 0. **/ gint mrp_time_day_of_week (mrptime t) { MrpTime t2; gint weekday; mrp_time2_set_epoch (&t2, t); weekday = g_date_get_weekday (&t2.date); if (weekday == 7) { weekday = 0; } return weekday; }
const gchar * mrp_time2_get_day_name (MrpTime *t) { GDateWeekday day; g_return_val_if_fail (t != NULL, NULL); day = g_date_get_weekday (&t->date); /* Weekday is mon-sun 1-7, while the array is sun-sat 0-6. */ if (day == 7) { day = 0; } return short_day_names[day]; }
static void _weekly_list_to_compact_string(GList *rs, GString *buf) { int dow_idx; char dow_present_bits = 0; int multiplier = -1; for (; rs != NULL; rs = rs->next) { Recurrence *r = (Recurrence*)rs->data; GDate date = recurrenceGetDate(r); GDateWeekday dow = g_date_get_weekday(&date); if (dow == G_DATE_BAD_WEEKDAY) { g_critical("bad weekday pretty-printing recurrence"); continue; } dow_present_bits |= (1 << (dow % 7)); // there's not necessarily a single multiplier, but for all intents // and purposes this will be fine. multiplier = recurrenceGetMultiplier(r); } g_string_printf(buf, "%s", _("Weekly")); if (multiplier > 1) { /* translators: %u is the recurrence multipler, i.e. this event should occur every %u'th week. */ g_string_append_printf(buf, _(" (x%u)"), multiplier); } g_string_append_printf(buf, ": "); // @@fixme: this is only Sunday-started weeks. :/ for (dow_idx = 0; dow_idx < 7; dow_idx++) { if ((dow_present_bits & (1 << dow_idx)) != 0) { gchar dbuf[10]; gnc_dow_abbrev(dbuf, 10, dow_idx); g_string_append_unichar(buf, g_utf8_get_char(dbuf)); } else { g_string_append_printf(buf, "-"); } } }
void utl_date_set_nearest_weekday (GDate *date, gint weekdays, gboolean month_mode) { gint day, start_day, days_in_month; gint i, j; if (weekdays == D_WEEK) return; g_return_if_fail (weekdays > D_BAD_DAY && weekdays <= D_WEEK); g_return_if_fail (g_date_valid (date)); day = g_date_get_weekday (date) - 1; if (month_mode == TRUE) { days_in_month = utl_date_get_days_in_month (date); start_day = g_date_get_day (date); for (i = 0; i < 7; i++) { if (weekdays & (1 << ((day + i) % 7))) break; } for (j = 0; j < 7; j++) { if (weekdays & (1 << ((day + 7 - j) % 7))) break; } if (start_day + i > days_in_month) i = 7; if (start_day - j < 1) j = 7; if (i <= j) { if (i > 0) g_date_add_days (date, i); } else { if (j > 0) g_date_subtract_days (date, j); } } else { for (i = 0; i < 7; i++) { if (weekdays & (1 << ((day + i) % 7))) break; } if (i > 0) g_date_add_days (date, i); } }
static void _monthly_append_when(Recurrence *r, GString *buf) { GDate date = recurrenceGetDate(r); if (recurrenceGetPeriodType(r) == PERIOD_LAST_WEEKDAY) { gchar day_name_buf[abbrev_day_name_bufsize]; gnc_dow_abbrev(day_name_buf, abbrev_day_name_bufsize, g_date_get_weekday(&date) % 7); /* translators: %s is an already-localized form of the day of the week. */ g_string_append_printf(buf, _("last %s"), day_name_buf); } else { /* translators: %u is the day of month */ g_string_append_printf(buf, "%u", g_date_get_day(&date)); } }
static void _setup_weekly_recurrence(GncFrequency *gf, Recurrence *r) { GDate recurrence_date; GDateWeekday day_of_week; guint multiplier = recurrenceGetMultiplier(r); const char *checkbox_widget_name; GtkWidget *weekday_checkbox; GtkWidget *multipler_spin = glade_xml_get_widget(gf->gxml, "weekly_spin"); gtk_spin_button_set_value(GTK_SPIN_BUTTON(multipler_spin), multiplier); recurrence_date = recurrenceGetDate(r); day_of_week = g_date_get_weekday(&recurrence_date); g_assert(day_of_week >= G_DATE_MONDAY && day_of_week <= G_DATE_SUNDAY); // this `mod 7' is explicit knowledge of the values of (monday=1)-based // GDateWeekday, vs. our (sunday=0)-based checkbox names array. checkbox_widget_name = CHECKBOX_NAMES[day_of_week % 7]; weekday_checkbox = glade_xml_get_widget(gf->gxml, checkbox_widget_name); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(weekday_checkbox), TRUE); }
guint utl_get_weekend_days_in_month (const GDate *date) { GDate *tmpdate = NULL; guint i, day, days, weekend_days; tmpdate = g_date_new_dmy (1, g_date_get_month (date), g_date_get_year (date)); g_return_val_if_fail (tmpdate != NULL, 0); days = utl_date_get_days_in_month (tmpdate); weekend_days = 0; for (i = 1; i <= days; i++) { g_date_set_day (tmpdate, i); day = g_date_get_weekday (tmpdate); if (day == G_DATE_SATURDAY || day == G_DATE_SUNDAY) { weekend_days++; } } g_date_free (tmpdate); return weekend_days; }
guint g_date_get_monday_week_of_year (const GDate *d) { GDateWeekday wd; guint day; GDate first; g_return_val_if_fail (g_date_valid (d), 0); if (!d->dmy) g_date_update_dmy (d); g_return_val_if_fail (d->dmy, 0); g_date_clear (&first, 1); g_date_set_dmy (&first, 1, 1, d->year); wd = g_date_get_weekday (&first) - 1; /* make Monday day 0 */ day = g_date_get_day_of_year (d) - 1; return ((day + wd)/7U + (wd == 0 ? 1 : 0)); }
void g_date_to_struct_tm (const GDate *d, struct tm *tm) { GDateWeekday day; g_return_if_fail (g_date_valid (d)); g_return_if_fail (tm != NULL); if (!d->dmy) g_date_update_dmy (d); g_return_if_fail (d->dmy); /* zero all the irrelevant fields to be sure they're valid */ /* On Linux and maybe other systems, there are weird non-POSIX * fields on the end of struct tm that choke strftime if they * contain garbage. So we need to 0 the entire struct, not just the * fields we know to exist. */ memset (tm, 0x0, sizeof (struct tm)); tm->tm_mday = d->day; tm->tm_mon = d->month - 1; /* 0-11 goes in tm */ tm->tm_year = ((int)d->year) - 1900; /* X/Open says tm_year can be negative */ day = g_date_get_weekday (d); if (day == 7) day = 0; /* struct tm wants days since Sunday, so Sunday is 0 */ tm->tm_wday = (int)day; tm->tm_yday = g_date_get_day_of_year (d) - 1; /* 0 to 365 */ tm->tm_isdst = -1; /* -1 means "information not available" */ }
static gint time_format_helper (const gchar *format, MrpTime *t, gchar *buffer) { gint len = 0; gchar str[5]; gint year, month, day; gint hour, min, sec; gint weekday; if (!format) { return 1; } year = g_date_get_year (&t->date); month = g_date_get_month (&t->date); day = g_date_get_day (&t->date); hour = t->hour; min = t->min; sec = t->sec; weekday = g_date_get_weekday (&t->date); if (weekday == 7) { weekday = 0; } while (*format) { register gchar c = *format++; register gint tmp; if (c != '%') { if (buffer) { buffer[len] = c; } len++; continue; } c = *format++; switch (c) { case 'a': /* The abbreviated weekday name (Mon, Tue, ...). */ if (buffer) { strcpy (buffer + len, short_day_names[weekday]); } len += strlen (short_day_names[weekday]); break; case 'A': /* The full weekday name (Monday, Tuesday, ...). */ if (buffer) { strcpy (buffer + len, day_names[weekday]); } len += strlen (day_names[weekday]); break; case 'b': /* The abbreviated month name (Jan, Feb, ...). */ if (buffer) { strcpy (buffer + len, short_month_names[month-1]); } len += strlen (short_month_names[month-1]); break; case 'B': /* The full month name (January, February, ...). */ if (buffer) { strcpy (buffer + len, month_names[month-1]); } len += strlen (month_names[month-1]); break; case 'd': /* The day of the month (01 - 31). */ if (buffer) { buffer[len] = day / 10 + '0'; buffer[len+1] = day - 10 * (day / 10) + '0'; } len += 2; break; case 'e': /* The day of the month (1 - 31). */ if (buffer) { if (day > 9) { buffer[len] = day / 10 + '0'; buffer[len+1] = day - 10 * (day / 10) + '0'; } else { buffer[len] = day + '0'; } } len += day > 9 ? 2 : 1; break; case 'H': /* The hour using a 24-hour clock (00 - 23). */ if (buffer) { buffer[len] = hour / 10 + '0'; buffer[len+1] = hour - 10 * (hour / 10) + '0'; } len += 2; break; case 'I': /* The hour using a 12-hour clock (01 - 12). */ if (buffer) { tmp = hour % 12; if (tmp == 0) { tmp = 12; } buffer[len] = tmp / 10 + '0'; buffer[len+1] = tmp - 10 * (tmp / 10) + '0'; } len += 2; break; case 'j': /* The day of the year (001 - 366). */ g_warning ("%%j not implemented."); if (buffer) { buffer[len] = ' '; buffer[len+1] = ' '; buffer[len+2] = ' '; } len += 3; break; case 'k': /* The hour using a 24-hour clock (0 to 23). */ if (buffer) { if (hour > 9) { buffer[len] = hour / 10 + '0'; buffer[len+1] = hour - 10 * (hour / 10) + '0'; } else { buffer[len] = hour + '0'; } } len += hour > 9 ? 2 : 1; break; case 'l': /* The hour using a 12-hour clock (1 - 12). */ tmp = hour % 12; if (tmp == 0) { tmp = 12; } if (buffer) { if (tmp > 9) { buffer[len] = tmp / 10 + '0'; buffer[len+1] = tmp - 10 * (tmp / 10) + '0'; } else { buffer[len] = tmp + '0'; } } len += tmp > 9 ? 2 : 1; break; case 'm': /* The month number (01 to 12). */ if (buffer) { buffer[len] = month / 10 + '0'; buffer[len+1] = month - 10 * (month / 10) + '0'; } len += 2; break; case 'M': /* The minute (00 - 59). */ if (buffer) { buffer[len] = min / 10 + '0'; buffer[len+1] = min - 10 * (min / 10) + '0'; } len += 2; break; case 'p': /* Either 'AM' or 'PM' according to the given time value. */ g_warning ("%%p not yet implemented."); if (buffer) { buffer[len] = ' '; buffer[len+1] = ' '; } len += 2; break; case 'P': /* Like %p but in lowercase. */ g_warning ("%%P not yet implemented."); if (buffer) { buffer[len] = ' '; buffer[len+1] = ' '; } len += 2; break; case 'R': /* The time in 24 hour notation (%H:%M). FIXME: use locale. */ if (buffer) { buffer[len] = hour / 10 + '0'; buffer[len+1] = hour - 10 * (hour / 10) + '0'; } len += 2; if (buffer) { buffer[len] = ':'; } len++; if (buffer) { buffer[len] = min / 10 + '0'; buffer[len+1] = min - 10 * (min / 10) + '0'; } len += 2; break; case 'S': /* The second (00 - 61). */ if (buffer) { buffer[len] = sec / 10 + '0'; buffer[len+1] = sec - 10 * (sec / 10) + '0'; } len += 2; break; case 'U': /* The week number, (1 - 53), starting with the first * Sunday as the first day of week 1. */ g_warning ("%%W not implemented"); break; case 'W': /* The week number, (1 - 53), starting with the first * Monday as the first day of week 1. */ snprintf (str, sizeof (str), "%d", mrp_time2_get_week_number (t, NULL)); if (buffer) { strcpy (buffer + len, str); } len += strlen (str); break; case 'y': /* The year without a century (range 00 to 99). */ if (buffer) { tmp = year % 100; buffer[len] = tmp / 10 + '0'; tmp -= 10 * (tmp / 10); buffer[len+1] = tmp + '0'; } len += 2; break; case 'Y': /* The year including the century. */ if (buffer) { tmp = year; buffer[len] = tmp / 1000 + '0'; tmp -= 1000 * (tmp / 1000); buffer[len+1] = tmp / 100 + '0'; tmp -= 100 * (tmp / 100); buffer[len+2] = tmp / 10 + '0'; tmp -= 10 * (tmp / 10); buffer[len+3] = tmp + '0'; } len += 4; break; default: g_warning ("Failed to parse format string."); break; } } if (buffer) { buffer[len] = 0; } /* Include the terminating zero. */ return len + 1; }
void mrp_time2_align_next (MrpTime *t, MrpTimeUnit unit) { GDateWeekday weekday; GDateMonth month; g_return_if_fail (t != NULL); switch (unit) { case MRP_TIME_UNIT_HOUR: t->min = 0; t->sec = 0; mrp_time2_add_hours (t, 1); break; case MRP_TIME_UNIT_TWO_HOURS: t->min = 0; t->sec = 0; mrp_time2_add_hours (t, 2 - t->hour % 2); break; case MRP_TIME_UNIT_HALFDAY: t->min = 0; t->sec = 0; if (t->hour < 12) { t->hour = 12; } else { t->hour = 0; mrp_time2_add_days (t, 1); } break; case MRP_TIME_UNIT_DAY: t->hour = 0; t->min = 0; t->sec = 0; mrp_time2_add_days (t, 1); break; case MRP_TIME_UNIT_WEEK: /* FIXME: We currently hardcode monday as week start .*/ weekday = g_date_get_weekday (&t->date); t->hour = 0; t->min = 0; t->sec = 0; mrp_time2_add_days (t, 8 - weekday); break; case MRP_TIME_UNIT_MONTH: t->hour = 0; t->min = 0; t->sec = 0; g_date_set_day (&t->date, 1); g_date_add_months (&t->date, 1); break; case MRP_TIME_UNIT_QUARTER: t->hour = 0; t->min = 0; t->sec = 0; g_date_set_day (&t->date, 1); month = g_date_get_month (&t->date); if (month >= 1 && month <= 3) { g_date_set_month (&t->date, 4); } else if (month >= 4 && month <= 6) { g_date_set_month (&t->date, 7); } else if (month >= 7 && month <= 9) { g_date_set_month (&t->date, 10); } else if (month >= 10 && month <= 12) { g_date_set_month (&t->date, 1); g_date_add_years (&t->date, 1); } break; case MRP_TIME_UNIT_HALFYEAR: g_date_set_day (&t->date, 1); t->hour = 0; t->min = 0; t->sec = 0; month = g_date_get_month (&t->date); if (month >= 1 && month <= 6) { g_date_set_month (&t->date, 7); } else if (month >= 7 && month <= 12) { g_date_set_month (&t->date, 1); g_date_add_years (&t->date, 1); } break; case MRP_TIME_UNIT_YEAR: t->hour = 0; t->min = 0; t->sec = 0; g_date_set_day (&t->date, 1); g_date_set_month (&t->date, 1); g_date_add_years (&t->date, 1); break; case MRP_TIME_UNIT_NONE: default: g_assert_not_reached (); } }
int main(int argc, char** argv) { GDate* d; guint32 j; GDateMonth m; GDateYear y, prev_y; GDateDay day; gchar buf[101]; gchar* loc; /* Try to get all the leap year cases. */ GDateYear check_years[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 98, 99, 100, 101, 102, 103, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 1598, 1599, 1600, 1601, 1602, 1650, 1651, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1961, 1962, 1963, 1964, 1965, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 3000, 3001, 3002, 3998, 3999, 4000, 4001, 4002, 4003 }; guint n_check_years = sizeof(check_years)/sizeof(GDateYear); guint i; gboolean discontinuity; g_print("checking GDate..."); TEST("sizeof(GDate) is not more than 8 bytes on this platform", sizeof(GDate) < 9); d = g_date_new(); TEST("Empty constructor produces invalid date", !g_date_valid(d)); g_date_free(d); d = g_date_new_dmy(1,1,1); TEST("January 1, Year 1 created and valid", g_date_valid(d)); j = g_date_get_julian(d); TEST("January 1, Year 1 is Julian date 1", j == 1); TEST("Returned month is January", g_date_get_month(d) == G_DATE_JANUARY); TEST("Returned day is 1", g_date_get_day(d) == 1); TEST("Returned year is 1", g_date_get_year(d) == 1); TEST("Bad month is invalid", !g_date_valid_month(G_DATE_BAD_MONTH)); TEST("Month 13 is invalid", !g_date_valid_month(13)); TEST("Bad day is invalid", !g_date_valid_day(G_DATE_BAD_DAY)); TEST("Day 32 is invalid", !g_date_valid_day(32)); TEST("Bad year is invalid", !g_date_valid_year(G_DATE_BAD_YEAR)); TEST("Bad julian is invalid", !g_date_valid_julian(G_DATE_BAD_JULIAN)); TEST("Bad weekday is invalid", !g_date_valid_weekday(G_DATE_BAD_WEEKDAY)); TEST("Year 2000 is a leap year", g_date_is_leap_year(2000)); TEST("Year 1999 is not a leap year", !g_date_is_leap_year(1999)); TEST("Year 1996 is a leap year", g_date_is_leap_year(1996)); TEST("Year 1600 is a leap year", g_date_is_leap_year(1600)); TEST("Year 2100 is not a leap year", !g_date_is_leap_year(2100)); TEST("Year 1800 is not a leap year", !g_date_is_leap_year(1800)); g_date_free(d); loc = setlocale(LC_ALL,""); if (loc) g_print("\nLocale set to %s\n", loc); else g_print("\nLocale unchanged\n"); d = g_date_new(); g_date_set_time(d, time(NULL)); TEST("Today is valid", g_date_valid(d)); g_date_strftime(buf,100,"Today is a %A, %x\n", d); g_print("%s", buf); g_date_set_time(d, 1); TEST("Beginning of Unix epoch is valid", g_date_valid(d)); g_date_strftime(buf,100,"1 second into the Unix epoch it was a %A, in the month of %B, %x\n", d); g_print("%s", buf); g_date_set_julian(d, 1); TEST("GDate's \"Julian\" epoch's first day is valid", g_date_valid(d)); g_date_strftime(buf,100,"Our \"Julian\" epoch begins on a %A, in the month of %B, %x\n", d); g_print("%s", buf); g_date_set_dmy(d, 10, 1, 2000); g_date_strftime(buf,100,"%x", d); g_date_set_parse(d, buf); /* Note: this test will hopefully work, but no promises. */ TEST("Successfully parsed a %x-formatted string", g_date_valid(d) && g_date_get_month(d) == 1 && g_date_get_day(d) == 10 && g_date_get_year(d) == 2000); if (failed) g_date_debug_print(d); g_date_free(d); j = G_DATE_BAD_JULIAN; i = 0; discontinuity = TRUE; y = check_years[0]; prev_y = G_DATE_BAD_YEAR; while (i < n_check_years) { guint32 first_day_of_year = G_DATE_BAD_JULIAN; guint16 days_in_year = g_date_is_leap_year(y) ? 366 : 365; guint sunday_week_of_year = 0; guint sunday_weeks_in_year = g_date_get_sunday_weeks_in_year(y); guint monday_week_of_year = 0; guint monday_weeks_in_year = g_date_get_monday_weeks_in_year(y); guint iso8601_week_of_year = 0; if (discontinuity) g_print(" (Break in sequence of requested years to check)\n"); g_print("Checking year %u", y); TEST("Year is valid", g_date_valid_year(y)); TEST("Number of Sunday weeks in year is 52 or 53", sunday_weeks_in_year == 52 || sunday_weeks_in_year == 53); TEST("Number of Monday weeks in year is 52 or 53", monday_weeks_in_year == 52 || monday_weeks_in_year == 53); m = 1; while (m < 13) { guint8 dim = g_date_get_days_in_month(m,y); GDate days[31]; /* This is the fast way, no allocation */ TEST("Sensible number of days in month", (dim > 0 && dim < 32)); TEST("Month between 1 and 12 is valid", g_date_valid_month(m)); day = 1; g_date_clear(days, 31); while (day <= dim) { guint i; GDate tmp; TEST("DMY triplet is valid", g_date_valid_dmy(day,m,y)); /* Create GDate with triplet */ d = &days[day-1]; TEST("Cleared day is invalid", !g_date_valid(d)); g_date_set_dmy(d,day,m,y); TEST("Set day is valid", g_date_valid(d)); if (m == G_DATE_JANUARY && day == 1) { first_day_of_year = g_date_get_julian(d); } g_assert(first_day_of_year != G_DATE_BAD_JULIAN); TEST("Date with DMY triplet is valid", g_date_valid(d)); TEST("Month accessor works", g_date_get_month(d) == m); TEST("Year accessor works", g_date_get_year(d) == y); TEST("Day of month accessor works", g_date_get_day(d) == day); TEST("Day of year is consistent with Julian dates", ((g_date_get_julian(d) + 1 - first_day_of_year) == (g_date_get_day_of_year(d)))); if (failed) { g_print("first day: %u this day: %u day of year: %u\n", first_day_of_year, g_date_get_julian(d), g_date_get_day_of_year(d)); } if (m == G_DATE_DECEMBER && day == 31) { TEST("Last day of year equals number of days in year", g_date_get_day_of_year(d) == days_in_year); if (failed) { g_print("last day: %u days in year: %u\n", g_date_get_day_of_year(d), days_in_year); } } TEST("Day of year is not more than number of days in the year", g_date_get_day_of_year(d) <= days_in_year); TEST("Monday week of year is not more than number of weeks in the year", g_date_get_monday_week_of_year(d) <= monday_weeks_in_year); if (failed) { g_print("Weeks in year: %u\n", monday_weeks_in_year); g_date_debug_print(d); } TEST("Monday week of year is >= than last week of year", g_date_get_monday_week_of_year(d) >= monday_week_of_year); if (g_date_get_weekday(d) == G_DATE_MONDAY) { TEST("Monday week of year on Monday 1 more than previous day's week of year", (g_date_get_monday_week_of_year(d) - monday_week_of_year) == 1); if ((m == G_DATE_JANUARY && day <= 4) || (m == G_DATE_DECEMBER && day >= 29)) { TEST("ISO 8601 week of year on Monday Dec 29 - Jan 4 is 1", (g_date_get_iso8601_week_of_year(d) == 1)); } else { TEST("ISO 8601 week of year on Monday 1 more than previous day's week of year", (g_date_get_iso8601_week_of_year(d) - iso8601_week_of_year) == 1); } } else { TEST("Monday week of year on non-Monday 0 more than previous day's week of year", (g_date_get_monday_week_of_year(d) - monday_week_of_year) == 0); if (!(day == 1 && m == G_DATE_JANUARY)) { TEST("ISO 8601 week of year on non-Monday 0 more than previous day's week of year (", (g_date_get_iso8601_week_of_year(d) - iso8601_week_of_year) == 0); } } monday_week_of_year = g_date_get_monday_week_of_year(d); iso8601_week_of_year = g_date_get_iso8601_week_of_year(d); TEST("Sunday week of year is not more than number of weeks in the year", g_date_get_sunday_week_of_year(d) <= sunday_weeks_in_year); if (failed) { g_date_debug_print(d); } TEST("Sunday week of year is >= than last week of year", g_date_get_sunday_week_of_year(d) >= sunday_week_of_year); if (g_date_get_weekday(d) == G_DATE_SUNDAY) { TEST("Sunday week of year on Sunday 1 more than previous day's week of year", (g_date_get_sunday_week_of_year(d) - sunday_week_of_year) == 1); } else { TEST("Sunday week of year on non-Sunday 0 more than previous day's week of year", (g_date_get_sunday_week_of_year(d) - sunday_week_of_year) == 0); } sunday_week_of_year = g_date_get_sunday_week_of_year(d); TEST("Date is equal to itself", g_date_compare(d,d) == 0); /*************** Increments ***********/ i = 1; while (i < 402) /* Need to get 400 year increments in */ { /***** Days ******/ tmp = *d; g_date_add_days(d, i); TEST("Adding days gives a value greater than previous", g_date_compare(d, &tmp) > 0); g_date_subtract_days(d, i); TEST("Forward days then backward days returns us to current day", g_date_get_day(d) == day); if (failed) { g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y); g_date_debug_print(d); } TEST("Forward days then backward days returns us to current month", g_date_get_month(d) == m); if (failed) { g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y); g_date_debug_print(d); } TEST("Forward days then backward days returns us to current year", g_date_get_year(d) == y); if (failed) { g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y); g_date_debug_print(d); } /******* Months ********/ tmp = *d; g_date_add_months(d, i); TEST("Adding months gives a larger value", g_date_compare(d, &tmp) > 0); g_date_subtract_months(d, i); TEST("Forward months then backward months returns us to current month", g_date_get_month(d) == m); if (failed) { g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y); g_date_debug_print(d); } TEST("Forward months then backward months returns us to current year", g_date_get_year(d) == y); if (failed) { g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y); g_date_debug_print(d); } if (day < 29) { /* Day should be unchanged */ TEST("Forward months then backward months returns us to current day", g_date_get_day(d) == day); if (failed) { g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y); g_date_debug_print(d); } } else { /* reset the day for later tests */ g_date_set_day(d, day); } /******* Years ********/ tmp = *d; g_date_add_years(d, i); TEST("Adding years gives a larger value", g_date_compare(d,&tmp) > 0); g_date_subtract_years(d, i); TEST("Forward years then backward years returns us to current month", g_date_get_month(d) == m); if (failed) { g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y); g_date_debug_print(d); } TEST("Forward years then backward years returns us to current year", g_date_get_year(d) == y); if (failed) { g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y); g_date_debug_print(d); } if (m != 2 && day != 29) { TEST("Forward years then backward years returns us to current day", g_date_get_day(d) == day); if (failed) { g_print(" (increment %u, dmy %u %u %u) ", i, day, m, y); g_date_debug_print(d); } } else { g_date_set_day(d, day); /* reset */ } i += 10; } /***** increment test relative to our local Julian count */ if (!discontinuity) { /* We can only run sequence tests between sequential years */ TEST("Julians are sequential with increment 1", j+1 == g_date_get_julian(d)); if (failed) { g_print("Out of sequence, prev: %u expected: %u got: %u\n", j, j+1, g_date_get_julian(d)); } g_date_add_days(d,1); TEST("Next day has julian 1 higher", g_date_get_julian(d) == j + 2); g_date_subtract_days(d, 1); if (j != G_DATE_BAD_JULIAN) { g_date_subtract_days(d, 1); TEST("Previous day has julian 1 lower", g_date_get_julian(d) == j); g_date_add_days(d, 1); /* back to original */ } } discontinuity = FALSE; /* goes away now */ fflush(stdout); fflush(stderr); j = g_date_get_julian(d); /* inc current julian */ ++day; } ++m; } g_print(" done\n"); ++i; prev_y = y; y = check_years[i]; if (prev_y == G_DATE_BAD_YEAR || (prev_y + 1) != y) discontinuity = TRUE; } g_print("\n%u tests passed, %u failed\n",passed, notpassed); return 0; }
static void check_valid(GDate *next, GDate *ref, GDate *start, guint16 mult, PeriodType pt, WeekendAdjust wadj) { gboolean valid; gint startToNext; /* FIXME: The WeekendAdjust argument is completely ignored for now. */ valid = g_date_valid(next); if (pt == PERIOD_ONCE && g_date_compare(start, ref) <= 0) do_test(!valid, "incorrectly valid"); else do_test(valid, "incorrectly invalid"); if (!valid) return; do_test(g_date_compare(ref, next) < 0, "next date not strictly later than ref date"); startToNext = g_date_get_julian(next) - g_date_get_julian(start); // Phase test switch (pt) { case PERIOD_YEAR: do_test((g_date_get_year(next) - g_date_get_year(start)) % mult == 0, "year period phase wrong"); // redundant mult *= 12; // fall through case PERIOD_END_OF_MONTH: if (pt == PERIOD_END_OF_MONTH) do_test(g_date_is_last_of_month(next), "end of month phase wrong"); // fall through case PERIOD_LAST_WEEKDAY: case PERIOD_NTH_WEEKDAY: case PERIOD_MONTH: { gint monthdiff; GDateDay day_start, day_next; monthdiff = (g_date_get_month(next) - g_date_get_month(start)) + 12 * (g_date_get_year(next) - g_date_get_year(start)); do_test(monthdiff % mult == 0, "month or year phase wrong"); if (pt == PERIOD_NTH_WEEKDAY || pt == PERIOD_LAST_WEEKDAY) { guint sweek, nweek; do_test(g_date_get_weekday(next) == g_date_get_weekday(start), "weekday phase wrong"); sweek = (g_date_get_day(start) - 1) / 7; nweek = (g_date_get_day(next) - 1) / 7; /* 3 cases: either the weeks agree, OR 'next' didn't have 5 of the weekday that 'start' did, so it's only the 4th, OR 'start' didn't have 5 of the weekday that 'next' does and we want the LAST weekday, so it's the 5th of that weekday */ do_test(sweek == nweek || (sweek == 4 && nweek == 3 && (g_date_get_day(next) + 7) > g_date_get_days_in_month( g_date_get_month(next), g_date_get_year(next))) || (sweek == 3 && nweek == 4 && (pt == PERIOD_LAST_WEEKDAY)), "week of month phase wrong"); } else { day_start = g_date_get_day(start); day_next = g_date_get_day(next); if (day_start < 28) do_test(day_start == day_next, "dom don't match"); else if (pt != PERIOD_END_OF_MONTH) { // the end of month case was already checked above. near // the end of the month, the days should still agree, // unless they can't because of a short month. do_test(day_start == day_next || g_date_is_last_of_month(next), "dom don't match and next is not eom"); } } } break; case PERIOD_WEEK: mult *= 7; // fall through case PERIOD_DAY: do_test((startToNext % mult) == 0, "week or day period phase wrong"); break; case PERIOD_ONCE: do_test(startToNext == 0, "period once not on start date"); break; default: do_test(FALSE, "invalid PeriodType"); break; } }
void calendar_draw_page (GtkPrintOperation *operation, GtkPrintContext *context, gint npage, gpointer user_data) { PangoLayout *layout; PangoFontDescription *month_name_font, *day_name_font, *day_num_font, *event_font; cairo_t *cr; GDate *date; gdouble page_width, page_height, day_width, day_height; gint text_width, text_height, header_height, event_height, mnf_height, dnf_height, duf_height; gint day, month, i, j; guint32 julian; gboolean monday, actual; gchar buffer[BUFFER_SIZE]; gint padding = config.cal_print_padding; GUI *appGUI = (GUI *) user_data; date = g_date_new_julian (g_date_get_julian (appGUI->cal->date)); g_return_if_fail (date != NULL); cr = gtk_print_context_get_cairo_context (context); layout = gtk_print_context_create_pango_layout (context); month_name_font = pango_font_description_from_string (config.cal_print_month_name_font); day_name_font = pango_font_description_from_string (config.cal_print_day_name_font); day_num_font = pango_font_description_from_string (config.cal_print_day_num_font); event_font = pango_font_description_from_string (config.cal_print_event_font); pango_layout_set_text (layout, "Aj", -1); pango_layout_set_font_description (layout, month_name_font); pango_layout_get_pixel_size (layout, NULL, &mnf_height); mnf_height *= 1.2; pango_layout_set_font_description (layout, day_name_font); pango_layout_get_pixel_size (layout, NULL, &dnf_height); dnf_height *= 1.2; pango_layout_set_font_description (layout, day_num_font); pango_layout_get_pixel_size (layout, NULL, &duf_height); page_width = gtk_print_context_get_width (context); day_width = page_width / 7; page_height = gtk_print_context_get_height (context); header_height = mnf_height + dnf_height; day_height = (page_height - header_height) / 6; event_height = day_height - duf_height - padding * 3; cairo_set_line_width (cr, 1); monday = (config.display_options & GUI_CALENDAR_WEEK_START_MONDAY) ? TRUE : FALSE; /* Month and year */ pango_layout_set_font_description (layout, month_name_font); g_date_strftime (buffer, BUFFER_SIZE, "%B %Y", date); pango_layout_set_text (layout, buffer, -1); pango_layout_get_pixel_size (layout, &text_width, NULL); cairo_move_to (cr, (page_width - text_width) / 2, 0); pango_cairo_show_layout (cr, layout); /* Day names */ pango_layout_set_font_description (layout, day_name_font); for (i = 0; i < 7; i++) { g_snprintf (buffer, BUFFER_SIZE, "%s", utl_get_day_name (i + 7 + monday, FALSE)); pango_layout_set_text (layout, buffer, -1); pango_layout_get_pixel_size (layout, &text_width, NULL); cairo_move_to (cr, day_width * i + (day_width - text_width) / 2, mnf_height); pango_cairo_show_layout (cr, layout); } /* Day */ g_date_set_day (date, 1); day = g_date_get_weekday (date); month = g_date_get_month (date); day = monday ? day - 1 : day % 7; if (day > 0) g_date_subtract_days (date, day); day = g_date_get_day (date); julian = g_date_get_julian (date); pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_width (layout, (day_width - padding * 2) * PANGO_SCALE); pango_layout_set_height (layout, event_height * PANGO_SCALE); pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); pango_layout_set_indent (layout, -4 * PANGO_SCALE); for (i = 0; i < 6; i++) { for (j = 0; j < 7; j++) { actual = (month == g_date_get_month (date)) ? TRUE : FALSE; day = g_date_get_day (date); cairo_rectangle (cr, day_width * j, header_height + day_height * i, day_width, day_height); if (actual) { cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); } else { cairo_set_source_rgb (cr, 0.8, 0.8, 0.8); } cairo_fill_preserve (cr); cairo_set_source_rgb (cr, 0, 0, 0); cairo_stroke (cr); pango_layout_set_font_description (layout, day_num_font); if (actual) { cairo_move_to (cr, day_width * j + padding, header_height + day_height * i + padding); if ((j == 0 && !monday) || (j == 5 && monday) || j == 6) { g_snprintf (buffer, BUFFER_SIZE, "<span color=\"red\">%d</span>", day); } else { g_snprintf (buffer, BUFFER_SIZE, "%d", day); } pango_layout_set_markup (layout, buffer, -1); pango_cairo_show_layout (cr, layout); cal_print_get_events (buffer, julian, appGUI); pango_layout_set_markup (layout, "", -1); pango_layout_set_text (layout, buffer, -1); pango_layout_set_font_description (layout, event_font); pango_layout_get_pixel_size (layout, NULL, &text_height); cairo_move_to (cr, day_width * j + padding, header_height + day_height * (i + 1) - text_height - padding); pango_cairo_show_layout (cr, layout); } else { cairo_move_to (cr, day_width * j + padding, header_height + day_height * i + padding); g_snprintf (buffer, BUFFER_SIZE, "<span color=\"white\">%d</span>", day); pango_layout_set_markup (layout, buffer, -1); pango_cairo_show_layout (cr, layout); } g_date_add_days (date, 1); julian++; } } g_date_free (date); pango_font_description_free (month_name_font); pango_font_description_free (day_name_font); pango_font_description_free (day_num_font); pango_font_description_free (event_font); g_object_unref (layout); }
void display_calendar (guint year, GUI *appGUI) { static MESSAGE selected_date[MAX_MONTHS * FULL_YEAR_COLS]; GDate *cdate; gint calendar_table[MAX_MONTHS * FULL_YEAR_COLS]; guint current_day, current_month, current_year; guint month; gint i, idx, day, first_day, days; gchar tmpbuf[BUFFER_SIZE], tmpbuf2[BUFFER_SIZE]; for (i = 0; i < MAX_MONTHS * FULL_YEAR_COLS; i++) { calendar_table[i] = -1; } cdate = g_date_new (); g_return_if_fail (cdate != NULL); for (month = G_DATE_JANUARY; month <= G_DATE_DECEMBER; month++) { g_date_set_dmy (cdate, 1, month, year); first_day = g_date_get_weekday (cdate); days = g_date_get_days_in_month (month, year); for (i = 1; i <= days; i++) { calendar_table[(month - 1) * FULL_YEAR_COLS + first_day + i - 2] = i; } } g_date_set_time_t (cdate, time (NULL)); current_day = g_date_get_day (cdate); current_month = g_date_get_month (cdate); current_year = g_date_get_year (cdate); for (month = G_DATE_JANUARY; month <= G_DATE_DECEMBER; month++) { for (i = 0; i < FULL_YEAR_COLS; i++) { idx = (month - 1) * FULL_YEAR_COLS + i; g_signal_handlers_disconnect_by_func (G_OBJECT (appGUI->cal->calendar_buttons[idx]), G_CALLBACK (select_date_day_cb), &selected_date[idx]); day = calendar_table[idx]; if (day > 0) { if (day == current_day && month == current_month && year == current_year) { g_snprintf (tmpbuf2, BUFFER_SIZE, "<b><u>%2d</u></b>", day); } else { g_snprintf (tmpbuf2, BUFFER_SIZE, "%2d", day); } if (i % 7 + 1 == G_DATE_SATURDAY || i % 7 + 1 == G_DATE_SUNDAY) { g_snprintf (tmpbuf, BUFFER_SIZE, "<span foreground='firebrick'>%s</span>", tmpbuf2); } else if (month % 2 == 0) { g_snprintf (tmpbuf, BUFFER_SIZE, "<span foreground='medium blue'>%s</span>", tmpbuf2); } else { g_strlcpy (tmpbuf, tmpbuf2, BUFFER_SIZE); } g_date_set_dmy (cdate, (GDateDay) day, month, (GDateYear) gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (appGUI->cal->fy_spinbutton))); selected_date[idx].data = (gpointer) g_date_get_julian (cdate); selected_date[idx].appGUI = appGUI; g_signal_connect (G_OBJECT (appGUI->cal->calendar_buttons[idx]), "clicked", G_CALLBACK (select_date_day_cb), &selected_date[idx]); gtk_button_set_label (GTK_BUTTON (appGUI->cal->calendar_buttons[idx]), ""); gtk_label_set_markup (GTK_LABEL (GTK_BIN (appGUI->cal->calendar_buttons[idx])->child), tmpbuf); gtk_widget_show (appGUI->cal->calendar_buttons[idx]); } else { gtk_button_set_label (GTK_BUTTON (appGUI->cal->calendar_buttons[idx]), ""); gtk_widget_hide (GTK_WIDGET (appGUI->cal->calendar_buttons[idx])); } } } g_date_free (cdate); }
/* This is the only real algorithm related to recurrences. It goes: Step 1) Go forward one period from the reference date. Step 2) Back up to align to the phase of the start date. */ void recurrenceNextInstance(const Recurrence *r, const GDate *ref, GDate *next) { PeriodType pt; const GDate *start; guint mult; WeekendAdjust wadj; g_return_if_fail(r); g_return_if_fail(ref); g_return_if_fail(g_date_valid(&r->start)); g_return_if_fail(g_date_valid(ref)); /* If the ref date comes before the start date then the next occurrence is always the start date, and we're done. */ start = &r->start; if (g_date_compare(ref, start) < 0) { g_date_set_julian(next, g_date_get_julian(start)); return; } g_date_set_julian(next, g_date_get_julian(ref)); /* start at refDate */ /* Step 1: move FORWARD one period, passing exactly one occurrence. */ mult = r->mult; pt = r->ptype; wadj = r->wadj; switch (pt) { case PERIOD_YEAR: mult *= 12; /* fall through */ case PERIOD_MONTH: case PERIOD_NTH_WEEKDAY: case PERIOD_LAST_WEEKDAY: case PERIOD_END_OF_MONTH: /* Takes care of short months. */ if (r->wadj == WEEKEND_ADJ_BACK && (pt == PERIOD_YEAR || pt == PERIOD_MONTH || pt == PERIOD_END_OF_MONTH) && (g_date_get_weekday(next) == G_DATE_SATURDAY || g_date_get_weekday(next) == G_DATE_SUNDAY)) { /* Allows the following Friday-based calculations to proceed if 'next' is between Friday and the target day. */ g_date_subtract_days(next, g_date_get_weekday(next) == G_DATE_SATURDAY ? 1 : 2); } if (r->wadj == WEEKEND_ADJ_BACK && (pt == PERIOD_YEAR || pt == PERIOD_MONTH || pt == PERIOD_END_OF_MONTH) && g_date_get_weekday(next) == G_DATE_FRIDAY) { GDate tmp_sat; GDate tmp_sun; g_date_set_julian(&tmp_sat, g_date_get_julian(next)); g_date_set_julian(&tmp_sun, g_date_get_julian(next)); g_date_add_days(&tmp_sat, 1); g_date_add_days(&tmp_sun, 2); if (pt == PERIOD_END_OF_MONTH) { if (g_date_is_last_of_month(next) || g_date_is_last_of_month(&tmp_sat) || g_date_is_last_of_month(&tmp_sun)) g_date_add_months(next, mult); else /* one fewer month fwd because of the occurrence in this month */ g_date_add_months(next, mult - 1); } else { if (g_date_get_day(&tmp_sat) == g_date_get_day(start)) { g_date_add_days(next, 1); g_date_add_months(next, mult); } else if (g_date_get_day(&tmp_sun) == g_date_get_day(start)) { g_date_add_days(next, 2); g_date_add_months(next, mult); } else if (g_date_get_day(next) >= g_date_get_day(start)) { g_date_add_months(next, mult); } else if (g_date_is_last_of_month(next)) { g_date_add_months(next, mult); } else if (g_date_is_last_of_month(&tmp_sat)) { g_date_add_days(next, 1); g_date_add_months(next, mult); } else if (g_date_is_last_of_month(&tmp_sun)) { g_date_add_days(next, 2); g_date_add_months(next, mult); } else { /* one fewer month fwd because of the occurrence in this month */ g_date_add_months(next, mult - 1); } } } else if ( g_date_is_last_of_month(next) || ((pt == PERIOD_MONTH || pt == PERIOD_YEAR) && g_date_get_day(next) >= g_date_get_day(start)) || ((pt == PERIOD_NTH_WEEKDAY || pt == PERIOD_LAST_WEEKDAY) && nth_weekday_compare(start, next, pt) <= 0) ) g_date_add_months(next, mult); else /* one fewer month fwd because of the occurrence in this month */ g_date_add_months(next, mult - 1); break; case PERIOD_WEEK: mult *= 7; /* fall through */ case PERIOD_DAY: g_date_add_days(next, mult); break; case PERIOD_ONCE: g_date_clear(next, 1); /* We already caught the case where ref is */ return; /* earlier than start, so this is invalid. */ default: PERR("Invalid period type"); break; } /* Step 2: Back up to align to the base phase. To ensure forward progress, we never subtract as much as we added (x % mult < mult). */ switch (pt) { case PERIOD_YEAR: case PERIOD_MONTH: case PERIOD_NTH_WEEKDAY: case PERIOD_LAST_WEEKDAY: case PERIOD_END_OF_MONTH: { guint dim, n_months; n_months = 12 * (g_date_get_year(next) - g_date_get_year(start)) + (g_date_get_month(next) - g_date_get_month(start)); g_date_subtract_months(next, n_months % mult); /* Ok, now we're in the right month, so we just have to align the day in one of the three possible ways. */ dim = g_date_get_days_in_month(g_date_get_month(next), g_date_get_year(next)); if (pt == PERIOD_LAST_WEEKDAY || pt == PERIOD_NTH_WEEKDAY) { gint wdresult = nth_weekday_compare(start, next, pt); if (wdresult < 0) { wdresult = -wdresult; g_date_subtract_days(next, wdresult); } else g_date_add_days(next, wdresult); } else if (pt == PERIOD_END_OF_MONTH || g_date_get_day(start) >= dim) g_date_set_day(next, dim); /* last day in the month */ else g_date_set_day(next, g_date_get_day(start)); /*same day as start*/ /* Adjust for dates on the weekend. */ if (pt == PERIOD_YEAR || pt == PERIOD_MONTH || pt == PERIOD_END_OF_MONTH) { if (g_date_get_weekday(next) == G_DATE_SATURDAY || g_date_get_weekday(next) == G_DATE_SUNDAY) { switch (wadj) { case WEEKEND_ADJ_BACK: g_date_subtract_days(next, g_date_get_weekday(next) == G_DATE_SATURDAY ? 1 : 2); break; case WEEKEND_ADJ_FORWARD: g_date_add_days(next, g_date_get_weekday(next) == G_DATE_SATURDAY ? 2 : 1); break; case WEEKEND_ADJ_NONE: default: break; } } } } break; case PERIOD_WEEK: case PERIOD_DAY: g_date_subtract_days(next, g_date_days_between(start, next) % mult); break; default: PERR("Invalid period type"); break; } }
void gnc_frequency_save_to_recurrence(GncFrequency *gf, GList **recurrences, GDate *out_start_date) { GDate start_date; gint page_index; gnc_date_edit_get_gdate(gf->startDate, &start_date); if (out_start_date != NULL) *out_start_date = start_date; if (recurrences == NULL) return; page_index = gtk_notebook_get_current_page(gf->nb); switch (page_index) { case PAGE_NONE: { // empty-recurrence list ~~ none. } break; case PAGE_ONCE: { Recurrence *r = g_new0(Recurrence, 1); recurrenceSet(r, 1, PERIOD_ONCE, &start_date, WEEKEND_ADJ_NONE); *recurrences = g_list_append(*recurrences, r); } break; case PAGE_DAILY: { gint multiplier = _get_multiplier_from_widget(gf, "daily_spin"); Recurrence *r = g_new0(Recurrence, 1); recurrenceSet(r, multiplier, PERIOD_DAY, &start_date, WEEKEND_ADJ_NONE); *recurrences = g_list_append(*recurrences, r); } break; case PAGE_WEEKLY: { int multiplier = _get_multiplier_from_widget(gf, "weekly_spin"); int checkbox_idx; for (checkbox_idx = 0; CHECKBOX_NAMES[checkbox_idx] != NULL; checkbox_idx++) { GDate *day_of_week_aligned_date; Recurrence *r; const char *day_widget_name = CHECKBOX_NAMES[checkbox_idx]; GtkWidget *weekday_checkbox = glade_xml_get_widget(gf->gxml, day_widget_name); if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(weekday_checkbox))) continue; day_of_week_aligned_date = g_date_new_julian(g_date_get_julian(&start_date)); // increment until we align on the DOW. while ((g_date_get_weekday(day_of_week_aligned_date) % 7) != checkbox_idx) g_date_add_days(day_of_week_aligned_date, 1); r = g_new0(Recurrence, 1); recurrenceSet(r, multiplier, PERIOD_WEEK, day_of_week_aligned_date, WEEKEND_ADJ_NONE); *recurrences = g_list_append(*recurrences, r); } } break; case PAGE_SEMI_MONTHLY: { int multiplier = _get_multiplier_from_widget(gf, "semimonthly_spin"); *recurrences = g_list_append(*recurrences, _get_day_of_month_recurrence(gf, &start_date, multiplier, "semimonthly_first", "semimonthly_first_weekend")); *recurrences = g_list_append(*recurrences, _get_day_of_month_recurrence(gf, &start_date, multiplier, "semimonthly_second", "semimonthly_second_weekend")); } break; case PAGE_MONTHLY: { int multiplier = _get_multiplier_from_widget(gf, "monthly_spin"); Recurrence *r = _get_day_of_month_recurrence(gf, &start_date, multiplier, "monthly_day", "monthly_weekend"); *recurrences = g_list_append(*recurrences, r); } break; default: g_error("unknown page index [%d]", page_index); break; } }
static void annum_shell_view_date_navigator_selection_changed_cb (AnnumShellView * self, ECalendarItem * calitem) { AnnumShellContent *prox_shell_content; GnomeCalendarViewType switch_to; GnomeCalendarViewType view_type; GnomeCalendar *calendar; ECalModel *model; GDate start_date, end_date; GDate new_start_date, new_end_date; icaltimetype tt; icaltimezone *timezone; time_t start, end, new_time; gboolean starts_on_week_start_day; gint new_days_shown; gint week_start_day; prox_shell_content = self->priv->prox_shell_content; calendar = annum_shell_content_get_calendar (prox_shell_content); model = gnome_calendar_get_model (calendar); view_type = gnome_calendar_get_view (calendar); switch_to = view_type; timezone = e_cal_model_get_timezone (model); week_start_day = e_cal_model_get_week_start_day (model); e_cal_model_get_time_range (model, &start, &end); time_to_gdate_with_zone (&start_date, start, timezone); time_to_gdate_with_zone (&end_date, end, timezone); if (view_type == GNOME_CAL_MONTH_VIEW) { EWeekView *week_view; ECalendarView *calendar_view; gboolean multi_week_view; gboolean compress_weekend; calendar_view = gnome_calendar_get_calendar_view (calendar, GNOME_CAL_MONTH_VIEW); week_view = E_WEEK_VIEW (calendar_view); multi_week_view = e_week_view_get_multi_week_view (week_view); compress_weekend = e_week_view_get_compress_weekend (week_view); if (week_start_day == 0 && (!multi_week_view || compress_weekend)) g_date_add_days (&start_date, 1); } g_date_subtract_days (&end_date, 1); e_calendar_item_get_selection (calitem, &new_start_date, &new_end_date); /* There used to be a check here to make sure the rest of the * code only ran when the date actually changed. We do not * this to simplify always having three columns for the day * view. */ new_days_shown = g_date_get_julian (&new_end_date) - g_date_get_julian (&new_start_date) + 1; /* If a complete week is selected we show the week view. * Note that if weekends are compressed and the week start * day is set to Sunday, we don't actually show complete * weeks in the week view, so this may need tweaking. */ starts_on_week_start_day = (g_date_get_weekday (&new_start_date) % 7 == week_start_day); /* Update selection to be in the new time range. */ tt = icaltime_null_time (); tt.year = g_date_get_year (&new_start_date); tt.month = g_date_get_month (&new_start_date); tt.day = g_date_get_day (&new_start_date); new_time = icaltime_as_timet_with_zone (tt, timezone); /* Switch views as appropriate, and change the number of * days or weeks shown. */ if (new_days_shown > 9) { if (view_type != GNOME_CAL_LIST_VIEW) { ECalendarView *calendar_view; calendar_view = gnome_calendar_get_calendar_view (calendar, GNOME_CAL_MONTH_VIEW); e_week_view_set_weeks_shown (E_WEEK_VIEW (calendar_view), (new_days_shown + 6) / 7); switch_to = GNOME_CAL_MONTH_VIEW; } } else if (new_days_shown == 7 && starts_on_week_start_day) switch_to = GNOME_CAL_WEEK_VIEW; else { ECalendarView *calendar_view; calendar_view = gnome_calendar_get_calendar_view (calendar, GNOME_CAL_DAY_VIEW); /* We always show three days */ if (new_days_shown == 1) new_days_shown = 3; e_day_view_set_days_shown (E_DAY_VIEW (calendar_view), new_days_shown); if (new_days_shown != 5 || !starts_on_week_start_day) switch_to = GNOME_CAL_DAY_VIEW; else if (view_type != GNOME_CAL_WORK_WEEK_VIEW) switch_to = GNOME_CAL_DAY_VIEW; } /* Make the views display things properly. */ gnome_calendar_update_view_times (calendar, new_time); gnome_calendar_set_view (calendar, switch_to); gnome_calendar_set_range_selected (calendar, TRUE); gnome_calendar_notify_dates_shown_changed (calendar); g_signal_emit (self, signals[DATE_CHANGED], 0, switch_to); }