on 444e2da help sign in
unity8/plugins/Utils/relativetimeformatter.cpp
199 lines 8.5 kB history raw
2#include "relativetimeformatter.h"
4#include <QDateTime>
6#include <QDebug>
8#include <glib.h>
9#include <locale.h>
10#include <langinfo.h>
11#include <libintl.h>
13RelativeTimeFormatter::RelativeTimeFormatter(QObject *parent)
14 : GDateTimeFormatter(parent)
18/* Check the system locale setting to see if the format is 24-hour
19 time or 12-hour time */
20gboolean
21is_locale_12h(void)
23 int i;
24 static const char *formats_24h[] = {"%H", "%R", "%T", "%OH", "%k", NULL};
25 const char* t_fmt = nl_langinfo(T_FMT);
27 for (i=0; formats_24h[i]!=NULL; i++)
28 if (strstr(t_fmt, formats_24h[i]) != NULL)
29 return FALSE;
31 return TRUE;
35typedef enum
37 DATE_PROXIMITY_TODAY,
38 DATE_PROXIMITY_YESTERDAY,
39 DATE_PROXIMITY_WEEK,
40 DATE_PROXIMITY_FAR
42date_proximity_t;
44static date_proximity_t
45getDateProximity(GDateTime* now, GDateTime* time)
47 date_proximity_t prox = DATE_PROXIMITY_FAR;
48 gint now_year, now_month, now_day;
49 gint time_year, time_month, time_day;
51 // does it happen today?
52 g_date_time_get_ymd(now, &now_year, &now_month, &now_day);
53 g_date_time_get_ymd(time, &time_year, &time_month, &time_day);
54 if ((now_year == time_year) && (now_month == time_month) && (now_day == time_day)) {
55 return DATE_PROXIMITY_TODAY;
56 }
58 // does it happen tomorrow?
59 GDateTime* tomorrow = g_date_time_add_days(now, -1);
60 gint tom_year, tom_month, tom_day;
61 g_date_time_get_ymd(tomorrow, &tom_year, &tom_month, &tom_day);
62 if ((tom_year == time_year) && (tom_month == time_month) && (tom_day == time_day))
63 return DATE_PROXIMITY_YESTERDAY;
64 g_date_time_unref(tomorrow);
66 // does it happen this week?
67 if (prox == DATE_PROXIMITY_FAR) {
68 GDateTime* week = g_date_time_add_days(now, -6);
69 GDateTime* week_bound = g_date_time_new_local(g_date_time_get_year(week),
70 g_date_time_get_month(week),
71 g_date_time_get_day_of_month(week),
72 23, 59, 59.9);
74 if (g_date_time_compare(time, week_bound) >= 0)
75 prox = DATE_PROXIMITY_WEEK;
77 g_date_time_unref(week_bound);
78 g_date_time_unref(week);
79 }
81 return DATE_PROXIMITY_FAR;
84/**
85 * _ a time today should be shown as just the time (e.g. “3:55 PM”)
86 * _ a full-day event today should be shown as “Today”
87 * _ a time any other day this week should be shown as the short version of the
88 * day and time (e.g. “Wed 3:55 PM”)
89 * _ a full-day event tomorrow should be shown as “Tomorrow”
90 * _ a full-day event another day this week should be shown as the
91 * weekday (e.g. “Friday”)
92 * _ a time after this week should be shown as the short version of the day,
93 * date, and time (e.g. “Wed 21 Apr 3:55 PM”)
94 * _ a full-day event after this week should be shown as the short version of
95 * the day and date (e.g. “Wed 21 Apr”).
96 * _ in addition, when presenting the times of upcoming events, the time should
97 * be followed by the timezone if it is different from the one the computer
98 * is currently set to. For example, “Wed 3:55 PM UTC−5”.
99 */
100char* generate_full_format_string_at_time (GDateTime* now,
101 GDateTime* then)
103 GString* ret = g_string_new (NULL);
105 if (then != NULL) {
106 const date_proximity_t prox = getDateProximity(now, then);
108 if (is_locale_12h()) {
109 switch (prox) {
110 case DATE_PROXIMITY_TODAY:
111 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
112 This format string is used for showing, on a 12-hour clock, times that happened today.
113 en_US example: "%l:%M %p" --> "1:00 PM" */
114 g_string_assign (ret, gettext("%l:%M %p"));
115 break;
117 case DATE_PROXIMITY_YESTERDAY:
118 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
119 This format string is used for showing, on a 12-hour clock, times that happen yesterday.
120 (\u2003 is a unicode em space which is slightly wider than a normal space.)
121 en_US example: "Yesterday\u2003%l:%M %p" --> "Tomorrow 1:00 PM" */
122 g_string_assign (ret, gettext("Yesterday\u2003%l:%M %p"));
123 break;
125 case DATE_PROXIMITY_WEEK:
126 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
127 This format string is used for showing, on a 12-hour clock, times that happened in the last week.
128 (\u2003 is a unicode em space which is slightly wider than a normal space.)
129 en_US example: "%a\u2003%l:%M %p" --> "Fri 1:00 PM" */
130 g_string_assign (ret, gettext("%a\u2003%l:%M %p"));
131 break;
133 case DATE_PROXIMITY_FAR:
134 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
135 This format string is used for showing, on a 12-hour clock, times that happened before a week from now.
136 (\u2003 is a unicode em space which is slightly wider than a normal space.)
137 en_US example: "%a %d %b\u2003%l:%M %p" --> "Fri Oct 31 1:00 PM"
138 en_GB example: "%a %b %d\u2003%l:%M %p" --> "Fri 31 Oct 1:00 PM" */
139 g_string_assign (ret, gettext("%a %d %b\u2003%l:%M %p"));
140 break;
141 }
142 } else {
143 switch (prox) {
144 case DATE_PROXIMITY_TODAY:
145 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
146 This format string is used for showing, on a 24-hour clock, times that happened today.
147 en_US example: "%H:%M" --> "13:00" */
148 g_string_assign (ret, gettext("%H:%M"));
149 break;
151 case DATE_PROXIMITY_YESTERDAY:
152 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
153 This format string is used for showing, on a 24-hour clock, times that happen yesterday.
154 (\u2003 is a unicode em space which is slightly wider than a normal space.)
155 en_US example: "Yesterday\u2003%l:%M %p" --> "Tomorrow 13:00" */
156 g_string_assign (ret, gettext("Yesterday\u2003%H:%M"));
157 break;
159 case DATE_PROXIMITY_WEEK:
160 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
161 This format string is used for showing, on a 24-hour clock, times that happened in the last week.
162 (\u2003 is a unicode em space which is slightly wider than a normal space.)
163 en_US example: "%a\u2003%H:%M" --> "Fri 13:00" */
164 g_string_assign (ret, gettext("%a\u2003%H:%M"));
165 break;
167 case DATE_PROXIMITY_FAR:
168 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
169 This format string is used for showing, on a 24-hour clock, times that happened before a week from now.
170 (\u2003 is a unicode em space which is slightly wider than a normal space.)
171 en_US example: "%a %d %b\u2003%H:%M" --> "Fri Oct 31 13:00"
172 en_GB example: "%a %b %d\u2003%H:%M" --> "Fri 31 Oct 13:00" */
173 g_string_assign (ret, gettext("%a %d %b\u2003%H:%M"));
174 break;
175 }
176 }
177 }
179 return g_string_free (ret, FALSE);
182QString RelativeTimeFormatter::format() const
184 GDateTime* now = g_date_time_new_from_unix_utc(QDateTime::currentMSecsSinceEpoch() / 1000);
185 if (!now) { return QString(); }
187 GDateTime* then = g_date_time_new_from_unix_local(time());
188 if (!then) { return QString(); }
190 char* time_format = generate_full_format_string_at_time(now, then);
192 QString str(QString::fromUtf8(time_format));
193 g_free(time_format);
195 g_date_time_unref(now);
196 g_date_time_unref(then);
198 return str;