diff options
-rw-r--r-- | src/contacts-contact-sheet.vala | 5 | ||||
-rw-r--r-- | src/core/contacts-birthday-chunk.vala | 25 | ||||
-rw-r--r-- | tests/core/test-birthday-chunk.vala | 17 |
3 files changed, 43 insertions, 4 deletions
diff --git a/src/contacts-contact-sheet.vala b/src/contacts-contact-sheet.vala index 953da41..b604bdc 100644 --- a/src/contacts-contact-sheet.vala +++ b/src/contacts-contact-sheet.vala @@ -317,11 +317,8 @@ public class Contacts.ContactSheet : Gtk.Widget { // Compare month and date so we can put a reminder string? subtitle = null; - int bd_m, bd_d, now_m, now_d; - birthday_chunk.birthday.to_local ().get_ymd (null, out bd_m, out bd_d); - new DateTime.now_local ().get_ymd (null, out now_m, out now_d); - if (bd_m == now_m && bd_d == now_d) { + if (birthday_chunk.is_today (new DateTime.now_local ())) { subtitle = _("Their birthday is today! 🎉"); } diff --git a/src/core/contacts-birthday-chunk.vala b/src/core/contacts-birthday-chunk.vala index d929dc5..6a87640 100644 --- a/src/core/contacts-birthday-chunk.vala +++ b/src/core/contacts-birthday-chunk.vala @@ -75,4 +75,29 @@ public class Contacts.BirthdayChunk : Chunk { requires (this.persona is BirthdayDetails) { yield ((BirthdayDetails) this.persona).change_birthday (this.birthday); } + + public bool is_today (DateTime now) + requires (this.birthday != null) { + int bd_m, bd_d, now_y, now_m, now_d; + _birthday.to_local().get_ymd (null, out bd_m, out bd_d); + now.get_ymd (out now_y, out now_m, out now_d); + + return (bd_m == now_m && bd_d == now_d) + || (is_leap_day (bd_m, bd_d) && is_birthday_of_leap_day_in_non_leap_year (now_y, now_m, now_d)); + } + + // February 28th is treated as birthday on non-leap years. + // This is consistent with the behaviour of evolution-data-server's Birthdays calendar: + // https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/88 + private bool is_birthday_of_leap_day_in_non_leap_year (int now_y, int now_m, int now_d) { + return now_m == 2 && now_d == 28 && !is_leap_year (now_y); + } + + private bool is_leap_year (int year) { + return ((DateYear) year).is_leap_year (); + } + + private bool is_leap_day (int month, int day) { + return month == 2 && day == 29; + } } diff --git a/tests/core/test-birthday-chunk.vala b/tests/core/test-birthday-chunk.vala index 826cb6d..d112379 100644 --- a/tests/core/test-birthday-chunk.vala +++ b/tests/core/test-birthday-chunk.vala @@ -19,6 +19,7 @@ void main (string[] args) { Test.init (ref args); Test.add_func ("/core/birthday-chunk/property_name_chunk", test_property_name); Test.add_func ("/core/birthday-chunk/is-empty", test_is_empty); + Test.add_func ("/core/birthday-chunk/leap-day-birthday", test_leap_day_birthday); Test.run (); } @@ -44,3 +45,19 @@ private void test_is_empty () { chunk.birthday = null; assert_true (chunk.is_empty); } + +void test_leap_day_birthday () { + var contact = new Contacts.Contact.empty (); + var chunk = (Contacts.BirthdayChunk) contact.create_chunk ("birthday", null); + assert_nonnull (chunk); + chunk.birthday = new DateTime.local (2020, 2, 29, 0, 0, 0); + + var leap_day = new DateTime.local (2024, 2, 29, 0, 0, 0); + assert_true (chunk.is_today (leap_day)); + + var feb_28_leap_year = new DateTime.local (2024, 2, 28, 0, 0, 0); + assert_false (chunk.is_today (feb_28_leap_year)); + + var feb_28_non_leap_year = new DateTime.local (2023, 2, 28, 0, 0, 0); + assert_true (chunk.is_today (feb_28_non_leap_year)); +}
\ No newline at end of file |