on e0990ee help sign in
unity8/plugins/Utils/relativetimeformatter.cpp
213 lines 9.1 kB history raw
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
18#include "relativetimeformatter.h"
20#include <QDateTime>
22#include <glib.h>
23#include <locale.h>
24#include <langinfo.h>
25#include <libintl.h>
27RelativeTimeFormatter::RelativeTimeFormatter(QObject *parent)
28 : GDateTimeFormatter(parent)
32/* Check the system locale setting to see if the format is 24-hour
33 time or 12-hour time */
34gboolean
35is_locale_12h(void)
37 int i;
38 static const char *formats_24h[] = {"%H", "%R", "%T", "%OH", "%k", NULL};
39 const char* t_fmt = nl_langinfo(T_FMT);
41 for (i=0; formats_24h[i]!=NULL; i++)
42 if (strstr(t_fmt, formats_24h[i]) != NULL)
43 return FALSE;
45 return TRUE;
49typedef enum
51 DATE_PROXIMITY_TODAY,
52 DATE_PROXIMITY_YESTERDAY,
53 DATE_PROXIMITY_WEEK,
54 DATE_PROXIMITY_FAR
56date_proximity_t;
58static date_proximity_t
59getDateProximity(GDateTime* now, GDateTime* time)
61 date_proximity_t prox = DATE_PROXIMITY_FAR;
62 gint now_year, now_month, now_day;
63 gint time_year, time_month, time_day;
65 // does it happen today?
66 g_date_time_get_ymd(now, &now_year, &now_month, &now_day);
67 g_date_time_get_ymd(time, &time_year, &time_month, &time_day);
68 if ((now_year == time_year) && (now_month == time_month) && (now_day == time_day)) {
69 return DATE_PROXIMITY_TODAY;
70 }
72 // does it happen tomorrow?
73 GDateTime* tomorrow = g_date_time_add_days(now, -1);
74 gint tom_year, tom_month, tom_day;
75 g_date_time_get_ymd(tomorrow, &tom_year, &tom_month, &tom_day);
76 if ((tom_year == time_year) && (tom_month == time_month) && (tom_day == time_day))
77 return DATE_PROXIMITY_YESTERDAY;
78 g_date_time_unref(tomorrow);
80 // does it happen this week?
81 if (prox == DATE_PROXIMITY_FAR) {
82 GDateTime* week = g_date_time_add_days(now, -6);
83 GDateTime* week_bound = g_date_time_new_local(g_date_time_get_year(week),
84 g_date_time_get_month(week),
85 g_date_time_get_day_of_month(week),
86 23, 59, 59.9);
88 if (g_date_time_compare(time, week_bound) >= 0)
89 prox = DATE_PROXIMITY_WEEK;
91 g_date_time_unref(week_bound);
92 g_date_time_unref(week);
93 }
95 return DATE_PROXIMITY_FAR;
98/**
99 * _ a time today should be shown as just the time (e.g. “3:55 PM”)
100 * _ a full-day event today should be shown as “Today”
101 * _ a time any other day this week should be shown as the short version of the
102 * day and time (e.g. “Wed 3:55 PM”)
103 * _ a full-day event tomorrow should be shown as “Tomorrow”
104 * _ a full-day event another day this week should be shown as the
105 * weekday (e.g. “Friday”)
106 * _ a time after this week should be shown as the short version of the day,
107 * date, and time (e.g. “Wed 21 Apr 3:55 PM”)
108 * _ a full-day event after this week should be shown as the short version of
109 * the day and date (e.g. “Wed 21 Apr”).
110 * _ in addition, when presenting the times of upcoming events, the time should
111 * be followed by the timezone if it is different from the one the computer
112 * is currently set to. For example, “Wed 3:55 PM UTC−5”.
113 */
114char* generate_full_format_string_at_time (GDateTime* now,
115 GDateTime* then)
117 GString* ret = g_string_new (NULL);
119 if (then != NULL) {
120 const date_proximity_t prox = getDateProximity(now, then);
122 if (is_locale_12h()) {
123 switch (prox) {
124 case DATE_PROXIMITY_TODAY:
125 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
126 This format string is used for showing, on a 12-hour clock, times that happened today.
127 en_US example: "%l:%M %p" --> "1:00 PM" */
128 g_string_assign (ret, gettext("%l:%M %p"));
129 break;
131 case DATE_PROXIMITY_YESTERDAY:
132 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
133 This format string is used for showing, on a 12-hour clock, times that happen yesterday.
134 (\u2003 is a unicode em space which is slightly wider than a normal space.)
135 en_US example: "Yesterday\u2003%l:%M %p" --> "Tomorrow 1:00 PM" */
136 g_string_assign (ret, gettext("Yesterday\u2003%l:%M %p"));
137 break;
139 case DATE_PROXIMITY_WEEK:
140 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
141 This format string is used for showing, on a 12-hour clock, times that happened in the last week.
142 (\u2003 is a unicode em space which is slightly wider than a normal space.)
143 en_US example: "%a\u2003%l:%M %p" --> "Fri 1:00 PM" */
144 g_string_assign (ret, gettext("%a\u2003%l:%M %p"));
145 break;
147 case DATE_PROXIMITY_FAR:
148 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
149 This format string is used for showing, on a 12-hour clock, times that happened before a week from now.
150 (\u2003 is a unicode em space which is slightly wider than a normal space.)
151 en_US example: "%a %d %b\u2003%l:%M %p" --> "Fri Oct 31 1:00 PM"
152 en_GB example: "%a %b %d\u2003%l:%M %p" --> "Fri 31 Oct 1:00 PM" */
153 g_string_assign (ret, gettext("%a %d %b\u2003%l:%M %p"));
154 break;
155 }
156 } else {
157 switch (prox) {
158 case DATE_PROXIMITY_TODAY:
159 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
160 This format string is used for showing, on a 24-hour clock, times that happened today.
161 en_US example: "%H:%M" --> "13:00" */
162 g_string_assign (ret, gettext("%H:%M"));
163 break;
165 case DATE_PROXIMITY_YESTERDAY:
166 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
167 This format string is used for showing, on a 24-hour clock, times that happen yesterday.
168 (\u2003 is a unicode em space which is slightly wider than a normal space.)
169 en_US example: "Yesterday\u2003%l:%M %p" --> "Tomorrow 13:00" */
170 g_string_assign (ret, gettext("Yesterday\u2003%H:%M"));
171 break;
173 case DATE_PROXIMITY_WEEK:
174 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
175 This format string is used for showing, on a 24-hour clock, times that happened in the last week.
176 (\u2003 is a unicode em space which is slightly wider than a normal space.)
177 en_US example: "%a\u2003%H:%M" --> "Fri 13:00" */
178 g_string_assign (ret, gettext("%a\u2003%H:%M"));
179 break;
181 case DATE_PROXIMITY_FAR:
182 /* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
183 This format string is used for showing, on a 24-hour clock, times that happened before a week from now.
184 (\u2003 is a unicode em space which is slightly wider than a normal space.)
185 en_US example: "%a %d %b\u2003%H:%M" --> "Fri Oct 31 13:00"
186 en_GB example: "%a %b %d\u2003%H:%M" --> "Fri 31 Oct 13:00" */
187 g_string_assign (ret, gettext("%a %d %b\u2003%H:%M"));
188 break;
189 }
190 }
191 }
193 return g_string_free (ret, FALSE);
196QString RelativeTimeFormatter::format() const
198 GDateTime* now = g_date_time_new_from_unix_utc(QDateTime::currentMSecsSinceEpoch() / 1000);
199 if (!now) { return QString(); }
201 GDateTime* then = g_date_time_new_from_unix_local(time());
202 if (!then) { return QString(); }
204 char* time_format = generate_full_format_string_at_time(now, then);
206 QString str(QString::fromUtf8(time_format));
207 g_free(time_format);
209 g_date_time_unref(now);
210 g_date_time_unref(then);
212 return str;