/*
* Copyright 2014 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include "relativetimeformatter.h"
#include
#include
#include
#include
#include
RelativeTimeFormatter::RelativeTimeFormatter(QObject *parent)
: GDateTimeFormatter(parent)
{
}
/* Check the system locale setting to see if the format is 24-hour
time or 12-hour time */
gboolean
is_locale_12h(void)
{
int i;
static const char *formats_24h[] = {"%H", "%R", "%T", "%OH", "%k", NULL};
const char* t_fmt = nl_langinfo(T_FMT);
for (i=0; formats_24h[i]!=NULL; i++)
if (strstr(t_fmt, formats_24h[i]) != NULL)
return FALSE;
return TRUE;
}
typedef enum
{
DATE_PROXIMITY_TODAY,
DATE_PROXIMITY_YESTERDAY,
DATE_PROXIMITY_WEEK,
DATE_PROXIMITY_FAR
}
date_proximity_t;
static date_proximity_t
getDateProximity(GDateTime* now, GDateTime* time)
{
date_proximity_t prox = DATE_PROXIMITY_FAR;
gint now_year, now_month, now_day;
gint time_year, time_month, time_day;
// does it happen today?
g_date_time_get_ymd(now, &now_year, &now_month, &now_day);
g_date_time_get_ymd(time, &time_year, &time_month, &time_day);
if ((now_year == time_year) && (now_month == time_month) && (now_day == time_day)) {
return DATE_PROXIMITY_TODAY;
}
// does it happen tomorrow?
GDateTime* tomorrow = g_date_time_add_days(now, -1);
gint tom_year, tom_month, tom_day;
g_date_time_get_ymd(tomorrow, &tom_year, &tom_month, &tom_day);
if ((tom_year == time_year) && (tom_month == time_month) && (tom_day == time_day))
return DATE_PROXIMITY_YESTERDAY;
g_date_time_unref(tomorrow);
// does it happen this week?
if (prox == DATE_PROXIMITY_FAR) {
GDateTime* week = g_date_time_add_days(now, -6);
GDateTime* week_bound = g_date_time_new_local(g_date_time_get_year(week),
g_date_time_get_month(week),
g_date_time_get_day_of_month(week),
23, 59, 59.9);
if (g_date_time_compare(time, week_bound) >= 0)
prox = DATE_PROXIMITY_WEEK;
g_date_time_unref(week_bound);
g_date_time_unref(week);
}
return DATE_PROXIMITY_FAR;
}
/**
* _ a time today should be shown as just the time (e.g. “3:55 PM”)
* _ a full-day event today should be shown as “Today”
* _ a time any other day this week should be shown as the short version of the
* day and time (e.g. “Wed 3:55 PM”)
* _ a full-day event tomorrow should be shown as “Tomorrow”
* _ a full-day event another day this week should be shown as the
* weekday (e.g. “Friday”)
* _ a time after this week should be shown as the short version of the day,
* date, and time (e.g. “Wed 21 Apr 3:55 PM”)
* _ a full-day event after this week should be shown as the short version of
* the day and date (e.g. “Wed 21 Apr”).
* _ in addition, when presenting the times of upcoming events, the time should
* be followed by the timezone if it is different from the one the computer
* is currently set to. For example, “Wed 3:55 PM UTC−5”.
*/
char* generate_full_format_string_at_time (GDateTime* now,
GDateTime* then)
{
GString* ret = g_string_new (NULL);
if (then != NULL) {
const date_proximity_t prox = getDateProximity(now, then);
if (is_locale_12h()) {
switch (prox) {
case DATE_PROXIMITY_TODAY:
/* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
This format string is used for showing, on a 12-hour clock, times that happened today.
en_US example: "%l:%M %p" --> "1:00 PM" */
g_string_assign (ret, gettext("%l:%M %p"));
break;
case DATE_PROXIMITY_YESTERDAY:
/* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
This format string is used for showing, on a 12-hour clock, times that happen yesterday.
(\u2003 is a unicode em space which is slightly wider than a normal space.)
en_US example: "Yesterday\u2003%l:%M %p" --> "Tomorrow 1:00 PM" */
g_string_assign (ret, gettext("Yesterday\u2003%l:%M %p"));
break;
case DATE_PROXIMITY_WEEK:
/* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
This format string is used for showing, on a 12-hour clock, times that happened in the last week.
(\u2003 is a unicode em space which is slightly wider than a normal space.)
en_US example: "%a\u2003%l:%M %p" --> "Fri 1:00 PM" */
g_string_assign (ret, gettext("%a\u2003%l:%M %p"));
break;
case DATE_PROXIMITY_FAR:
/* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
This format string is used for showing, on a 12-hour clock, times that happened before a week from now.
(\u2003 is a unicode em space which is slightly wider than a normal space.)
en_US example: "%a %d %b\u2003%l:%M %p" --> "Fri Oct 31 1:00 PM"
en_GB example: "%a %b %d\u2003%l:%M %p" --> "Fri 31 Oct 1:00 PM" */
g_string_assign (ret, gettext("%a %d %b\u2003%l:%M %p"));
break;
}
} else {
switch (prox) {
case DATE_PROXIMITY_TODAY:
/* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
This format string is used for showing, on a 24-hour clock, times that happened today.
en_US example: "%H:%M" --> "13:00" */
g_string_assign (ret, gettext("%H:%M"));
break;
case DATE_PROXIMITY_YESTERDAY:
/* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
This format string is used for showing, on a 24-hour clock, times that happen yesterday.
(\u2003 is a unicode em space which is slightly wider than a normal space.)
en_US example: "Yesterday\u2003%l:%M %p" --> "Tomorrow 13:00" */
g_string_assign (ret, gettext("Yesterday\u2003%H:%M"));
break;
case DATE_PROXIMITY_WEEK:
/* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
This format string is used for showing, on a 24-hour clock, times that happened in the last week.
(\u2003 is a unicode em space which is slightly wider than a normal space.)
en_US example: "%a\u2003%H:%M" --> "Fri 13:00" */
g_string_assign (ret, gettext("%a\u2003%H:%M"));
break;
case DATE_PROXIMITY_FAR:
/* Translators, please edit/rearrange these strftime(3) tokens to suit your locale!
This format string is used for showing, on a 24-hour clock, times that happened before a week from now.
(\u2003 is a unicode em space which is slightly wider than a normal space.)
en_US example: "%a %d %b\u2003%H:%M" --> "Fri Oct 31 13:00"
en_GB example: "%a %b %d\u2003%H:%M" --> "Fri 31 Oct 13:00" */
g_string_assign (ret, gettext("%a %d %b\u2003%H:%M"));
break;
}
}
}
return g_string_free (ret, FALSE);
}
QString RelativeTimeFormatter::format() const
{
GDateTime* now = g_date_time_new_from_unix_utc(QDateTime::currentMSecsSinceEpoch() / 1000);
if (!now) { return QString(); }
GDateTime* then = g_date_time_new_from_unix_local(time());
if (!then) { return QString(); }
char* time_format = generate_full_format_string_at_time(now, then);
QString str(QString::fromUtf8(time_format));
g_free(time_format);
g_date_time_unref(now);
g_date_time_unref(then);
return str;
}