KMime

kmime_dateformatter.cpp
Go to the documentation of this file.
1 /*
2  kmime_dateformatter.cpp
3 
4  KMime, the KDE Internet mail/usenet news message library.
5  SPDX-FileCopyrightText: 2001 the KMime authors.
6  See file AUTHORS for details
7 
8  SPDX-License-Identifier: LGPL-2.0-or-later
9 */
10 /**
11  @file
12  This file is part of the API for handling @ref MIME data and
13  defines the DateFormatter class.
14 
15  @brief
16  Defines the DateFormatter class.
17 
18  @authors the KMime authors (see AUTHORS file)
19 */
20 
21 #include "kmime_dateformatter.h"
22 
23 #include <config-kmime.h>
24 
25 #include <QTextStream>
26 #include <QIODevice>
27 #include <KLocalizedString>
28 
29 using namespace KMime;
30 
31 namespace KMime {
32 
33 class DateFormatterPrivate {
34 public:
35  DateFormatterPrivate()
36  {}
37 
38  /**
39  Returns a QString containing the specified time_t @p t formatted
40  using the #Fancy #FormatType.
41 
42  @param t is the time_t to use for formatting.
43  */
44  QString fancy(time_t t);
45 
46  /**
47  Returns a QString containing the specified time_t @p t formatted
48  using the #Localized #FormatType.
49 
50  @param t is the time_t to use for formatting.
51  @param shortFormat if true, create the short version of the date string.
52  @param lang is a QString containing the language to use.
53  */
54  static QString localized(time_t t, bool shortFormat = true, const QString &lang = QString());
55 
56  /**
57  Returns a QString containing the specified time_t @p t formatted
58  with the ctime() function.
59 
60  @param t is the time_t to use for formatting.
61  */
62  static QString cTime(time_t t);
63 
64  /**
65  Returns a QString containing the specified time_t @p t in the
66  "%Y-%m-%d %H:%M:%S" #Iso #FormatType.
67 
68  @param t is the time_t to use for formatting.
69  */
70  static QString isoDate(time_t t);
71 
72  /**
73  Returns a QString containing the specified time_t @p t in the
74  #Rfc #FormatType.
75 
76  @param t is the time_t to use for formatting.
77  */
78  static QString rfc2822(time_t t);
79 
80  /**
81  Returns a QString containing the specified time_t @p t formatted
82  with a previously specified custom format.
83 
84  @param t time used for formatting
85  */
86  QString custom(time_t t) const;
87 
88  /**
89  Returns a QString that identifies the timezone (eg."-0500")
90  of the specified time_t @p t.
91 
92  @param t time to compute timezone from.
93  */
94  static QByteArray zone(time_t t);
95 
97  time_t mTodayOneSecondBeforeMidnight = 0;
98  QString mCustomFormat;
99 };
100 
101 }
102 
104  d(new DateFormatterPrivate)
105 {
106  d->mFormat = ftype;
107 }
108 
110 
112 {
113  return d->mFormat;
114 }
115 
117 {
118  d->mFormat = ftype;
119 }
120 
121 QString DateFormatter::dateString(time_t t, const QString &lang, bool shortFormat) const
122 {
123  switch (d->mFormat) {
124  case Fancy:
125  return d->fancy(t);
126  case Localized:
127  return d->localized(t, shortFormat, lang);
128  case CTime:
129  return d->cTime(t);
130  case Iso:
131  return d->isoDate(t);
132  case Rfc:
133  return d->rfc2822(t);
134  case Custom:
135  return d->custom(t);
136  }
137  return {};
138 }
139 
140 QString DateFormatter::dateString(const QDateTime &dt, const QString &lang, bool shortFormat) const
141 {
142  return dateString(dt.toLocalTime().toSecsSinceEpoch(), lang, shortFormat);
143 }
144 
145 QString DateFormatterPrivate::rfc2822(time_t t)
146 {
147  QDateTime tmp;
148  QString ret;
149 
150  tmp.setSecsSinceEpoch(t);
151 
152  ret = tmp.toString(QStringLiteral("ddd, dd MMM yyyy hh:mm:ss "));
153  ret += QLatin1String(zone(t));
154 
155  return ret;
156 }
157 
158 QString DateFormatterPrivate::custom(time_t t) const
159 {
160  if (mCustomFormat.isEmpty()) {
161  return {};
162  }
163 
164  int z = mCustomFormat.indexOf(QLatin1Char('Z'));
165  QDateTime dt;
166  QString ret = mCustomFormat;
167 
168  dt.setSecsSinceEpoch(t);
169  if (z != -1) {
170  ret.replace(z, 1, QLatin1String(zone(t)));
171  }
172 
173  ret = dt.toString(ret);
174 
175  return ret;
176 }
177 
179 {
180  d->mCustomFormat = format;
181  d->mFormat = Custom;
182 }
183 
185 {
186  return d->mCustomFormat;
187 }
188 
189 QByteArray DateFormatterPrivate::zone(time_t t)
190 {
191 #if HAVE_TIMEZONE || HAVE_TM_GMTOFF
192  struct tm *local = localtime(&t);
193 #endif
194 
195 #if HAVE_TIMEZONE
196 
197  //hmm, could make hours & mins static
198  int secs = qAbs(timezone);
199  int neg = (timezone > 0) ? 1 : 0;
200  int hours = secs / 3600;
201  int mins = (secs - hours * 3600) / 60;
202 
203  // adjust to daylight
204  if (local->tm_isdst > 0) {
205  if (neg) {
206  --hours;
207  } else {
208  ++hours;
209  }
210  }
211 
212 #elif HAVE_TM_GMTOFF
213 
214  int secs = qAbs(local->tm_gmtoff);
215  int neg = (local->tm_gmtoff < 0) ? 1 : 0;
216  int hours = secs / 3600;
217  int mins = (secs - hours * 3600) / 60;
218 
219 #else
220 
221  QDateTime d1 = QDateTime::fromString(QString::fromLatin1(asctime(gmtime(&t))));
222  QDateTime d2 = QDateTime::fromString(QString::fromLatin1(asctime(localtime(&t))));
223  int secs = d1.secsTo(d2);
224  int neg = (secs < 0) ? 1 : 0;
225  secs = qAbs(secs);
226  int hours = secs / 3600;
227  int mins = (secs - hours * 3600) / 60;
228 
229 #endif /* HAVE_TIMEZONE */
230 
231  QByteArray ret;
233  s << (neg ? '-' : '+')
234  << qSetFieldWidth(2) << qSetPadChar(QLatin1Char('0'))
235  << Qt::right
236  << hours << mins;
237  //old code: ret.sprintf( "%c%.2d%.2d", (neg) ? '-' : '+', hours, mins );
238 
239  return ret;
240 }
241 
242 QString DateFormatterPrivate::fancy(time_t t)
243 {
244  auto locale = QLocale::system();
245 
246  if (t <= 0) {
247  return i18nc("invalid time specified", "unknown");
248  }
249 
250  if (mTodayOneSecondBeforeMidnight < time(nullptr)) {
251  // determine time_t value of today 23:59:59
252  const QDateTime today(QDate::currentDate(), QTime(23, 59, 59));
253  mTodayOneSecondBeforeMidnight = today.toSecsSinceEpoch();
254  }
255 
256  QDateTime old;
257  old.setSecsSinceEpoch(t);
258 
259  if (mTodayOneSecondBeforeMidnight >= t) {
260  const time_t diff = mTodayOneSecondBeforeMidnight - t;
261  if (diff < 7 * 24 * 60 * 60) {
262  if (diff < 24 * 60 * 60) {
263  return i18n("Today %1",
264  locale.toString(old.time(), QLocale::ShortFormat));
265  }
266  if (diff < 2 * 24 * 60 * 60) {
267  return i18n("Yesterday %1",
268  locale.toString(old.time(), QLocale::ShortFormat));
269  }
270  for (int i = 3; i < 8; i++) {
271  if (diff < i * 24 * 60 * 60) {
272  return i18nc("1. weekday, 2. time", "%1 %2" ,
273  locale.dayName(old.date().dayOfWeek(), QLocale::LongFormat),
274  locale.toString(old.time(), QLocale::ShortFormat));
275  }
276  }
277  }
278  }
279 
280  return locale.toString(old, QLocale::ShortFormat);
281 }
282 
283 QString DateFormatterPrivate::localized(time_t t, bool shortFormat, const QString &lang)
284 {
285  QDateTime tmp;
286  QString ret;
287  auto locale = QLocale::system();
288 
289  tmp.setSecsSinceEpoch(t);
290 
291  if (!lang.isEmpty()) {
292  locale = QLocale(lang);
293  ret = locale.toString(tmp, (shortFormat ? QLocale::ShortFormat : QLocale::LongFormat));
294  } else {
295  ret = locale.toString(tmp, (shortFormat ? QLocale::ShortFormat : QLocale::LongFormat));
296  }
297 
298  return ret;
299 }
300 
301 QString DateFormatterPrivate::cTime(time_t t)
302 {
303  return QString::fromLatin1(ctime(&t)).trimmed();
304 }
305 
306 QString DateFormatterPrivate::isoDate(time_t t)
307 {
308  char cstr[64];
309  strftime(cstr, 63, "%Y-%m-%d %H:%M:%S", localtime(&t));
310  return QLatin1String(cstr);
311 }
312 
314  const QString &data, bool shortFormat)
315 {
316  DateFormatter f(ftype);
317  if (ftype == Custom) {
318  f.setCustomFormat(data);
319  }
320  return f.dateString(t, data, shortFormat);
321 }
322 
323 QString DateFormatter::formatCurrentDate(FormatType ftype, const QString &data, bool shortFormat)
324 {
325  DateFormatter f(ftype);
326  if (ftype == Custom) {
327  f.setCustomFormat(data);
328  }
329  return f.dateString(time(nullptr), data, shortFormat);
330 }
DateFormatter(FormatType ftype=DateFormatter::Fancy)
Constructs a date formatter with a default FormatType.
QTextStream & right(QTextStream &stream)
@ CTime
ctime "Sun Mar 31 02:08:35 2002"
void setFormat(FormatType ftype)
Sets the date format to ftype.
@ Iso
iso "2002-03-31 02:08:35"
QTime time() const const
QString trimmed() const const
FormatType format() const
Returns the FormatType currently set.
void setSecsSinceEpoch(qint64 secs)
Defines the DateFormatter class.
static QString formatCurrentDate(DateFormatter::FormatType ftype, const QString &data=QString(), bool shortFormat=true)
Convenience function, same as formatDate() but returns the current time formatted.
void setCustomFormat(const QString &format)
Sets the custom format for date to string conversions to format.
~DateFormatter()
Destroys the date formatter.
QLocale system()
QString i18n(const char *text, const TYPE &arg...)
@ Fancy
fancy "Today 02:08:35"
qint64 secsTo(const QDateTime &other) const const
QString customFormat() const
Returns the custom format string.
bool isEmpty() const const
@ Custom
custom "whatever you like"
QDate currentDate()
QDateTime fromString(const QString &string, Qt::DateFormat format)
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString & replace(int position, int n, QChar after)
QString dateString(time_t t, const QString &lang=QString(), bool shortFormat=true) const
Constructs a formatted date string from time_t t.
QDateTime toLocalTime() const const
FormatType
The different types of date formats.
LocaleWrapper locale()
A class for abstracting date formatting.
qint64 toSecsSinceEpoch() const const
static QString formatDate(DateFormatter::FormatType ftype, time_t t, const QString &data=QString(), bool shortFormat=true)
Convenience function dateString.
@ Rfc
rfc "Sun, 31 Mar 2002 02:08:35 -0500"
QString fromLatin1(const char *str, int size)
QDate date() const const
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString toString(Qt::DateFormat format) const const
int dayOfWeek() const const
@ Localized
localized "2002-03-31 02:08"
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Aug 11 2022 03:54:30 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.