summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/contacts-contact-sheet.vala5
-rw-r--r--src/core/contacts-birthday-chunk.vala25
-rw-r--r--tests/core/test-birthday-chunk.vala17
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