From 0bea84adce98b7c930d923174a61d4dc74de0b55 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Mon, 27 Jul 2026 20:55:52 +0300 Subject: [PATCH] message: add utc-offset field Add a new db field for storing UTC-offset for the Date: field. --- lib/message/mu-fields.hh | 15 +++++++++++++-- lib/message/mu-message.cc | 7 ++++++- lib/message/mu-mime-object.cc | 13 +++++++++---- lib/message/mu-mime-object.hh | 11 +++++++++-- mu/mu-cmd-view.cc | 2 +- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/lib/message/mu-fields.hh b/lib/message/mu-fields.hh index 3368de22..39b376c9 100644 --- a/lib/message/mu-fields.hh +++ b/lib/message/mu-fields.hh @@ -68,7 +68,7 @@ struct Field { // XXX: re-order when we update the db-schema. Labels, /**< Labels */ - + UtcOffset, /**< Offset from UTC for the sent Date */ // _count_ /**< Number of Ids */ }; @@ -465,6 +465,8 @@ inline constexpr std::array Field::Flag::NormalTerm | Field::Flag::PhrasableTerm, }, + // at the end for now; reordering when we're bumping + // the db schema version. { Field::Id::Labels, Field::Type::StringList, @@ -475,7 +477,16 @@ inline constexpr std::array Field::Flag::BooleanTerm | Field::Flag::Value | Field::Flag::IncludeInSexp -, + }, + { + Field::Id::UtcOffset, + Field::Type::Integer, + "utc-offset", {}, + "UTC offset for Date in seconds:", + {}, + 'u', + Field::Flag::Value | + Field::Flag::IncludeInSexp }, }}; diff --git a/lib/message/mu-message.cc b/lib/message/mu-message.cc index fbd6df60..3a2fa106 100644 --- a/lib/message/mu-message.cc +++ b/lib/message/mu-message.cc @@ -741,7 +741,10 @@ fill_document(Message::Private& priv) doc.add(field.id, priv.ctime); break; case Field::Id::Date: - doc.add(field.id, mime_msg.date()); + if (const auto& date{mime_msg.date()}; date) { + doc.add(field.id, date->first); + doc.add(Field::Id::UtcOffset, date->second); + } break; case Field::Id::EmbeddedText: doc.add(field.id, priv.embedded); @@ -801,6 +804,8 @@ fill_document(Message::Private& priv) case Field::Id::To: doc.add(field.id, mime_msg.contacts(Contact::Type::To)); break; + case Field::Id::UtcOffset: + break; // handle already as part of Date: /* LCOV_EXCL_START */ case Field::Id::_count_: default: diff --git a/lib/message/mu-mime-object.cc b/lib/message/mu-mime-object.cc index 684b41a1..27d974fa 100644 --- a/lib/message/mu-mime-object.cc +++ b/lib/message/mu-mime-object.cc @@ -334,13 +334,17 @@ MimeMessage::make_from_text(const std::string& text) return make_from_stream(std::move(stream)); } -Option +Option MimeMessage::date() const noexcept { if (/*const*/GDateTime *dt{g_mime_message_get_date(self())}; !dt) return Nothing; - else - return g_date_time_to_unix(dt); + else { + constexpr auto usecs_per_sec = 1'000'000; + return Date{ g_date_time_to_unix(dt), + g_date_time_get_utc_offset(dt) / usecs_per_sec }; + + } } constexpr Option @@ -431,7 +435,8 @@ MimeMessage::contacts(Contact::Type ctype) const noexcept return {}; Contacts contacts; - add_contacts(addrs, ctype, date().value_or(0), contacts); + const auto mdate{date()}; + add_contacts(addrs, ctype, mdate ? mdate->first : 0, contacts); return contacts; } diff --git a/lib/message/mu-mime-object.hh b/lib/message/mu-mime-object.hh index d0839faf..dae4a53c 100644 --- a/lib/message/mu-mime-object.hh +++ b/lib/message/mu-mime-object.hh @@ -1047,12 +1047,19 @@ public: return Mu::to_string_opt(g_mime_message_get_subject(self())); } + using Date = std::pair; + /**< Date type */ + /** - * Gets the date if it exists, or nullopt otherwise. + * Gets a date, utf-offset pair if it exists, or nullopt otherwise. + * + * The date is the number of seconds since epoch (i.e., unix time), + * while utf-offset is the number of seconds offset from UTC + * (i.e., negative numbers west of GMT, positive numbers for east) * * @return a time_t value (expressed as a 64-bit number) or nullopt */ - Option date() const noexcept; + Option date() const noexcept; /** diff --git a/mu/mu-cmd-view.cc b/mu/mu-cmd-view.cc index 5e528447..60f8fc60 100644 --- a/mu/mu-cmd-view.cc +++ b/mu/mu-cmd-view.cc @@ -307,7 +307,7 @@ test_view_sexp() g_assert_true(::stat(msgpath.c_str(), &statbuf) == 0); const auto expected = mu_format( - R"((:path "{}" :size 638 :changed ({} {} 0) :date (19930 8345 0) :flags (unread) :from ((:email "test@example.com" :name "Test")) :message-id "10374608.109906.11909.20115aabbccdd.MSGID@mailinglijst.nl" :priority normal :subject "vla" :to ((:email "abc@example.com"))) + R"((:path "{}" :size 638 :changed ({} {} 0) :date (19930 8345 0) :utc-offset 7200 :flags (unread) :from ((:email "test@example.com" :name "Test")) :message-id "10374608.109906.11909.20115aabbccdd.MSGID@mailinglijst.nl" :priority normal :subject "vla" :to ((:email "abc@example.com"))) )", msgpath, statbuf.st_ctime >> 16,