1/*
2 This file is part of the KDE Frameworks
3
4 SPDX-FileCopyrightText: 2013 Alex Merry <alex.merry@kdemail.net>
5 SPDX-FileCopyrightText: 2013 John Layt <jlayt@kde.org>
6 SPDX-FileCopyrightText: 2010 Michael Leupold <lemma@confuego.org>
7 SPDX-FileCopyrightText: 2009 Michael Pyne <mpyne@kde.org>
8 SPDX-FileCopyrightText: 2008 Albert Astals Cid <aacid@kde.org>
9
10 SPDX-License-Identifier: LGPL-2.0-or-later
11*/
12
13#ifndef KFORMAT_H
14#define KFORMAT_H
15
16#include <kcoreaddons_export.h>
17
18#include <QLocale>
19#include <QSharedPointer>
20#include <QString>
21
22class QDate;
23class QDateTime;
24
25class KFormatPrivate;
26
27/**
28 * \file kformat.h
29 */
30
31/*
32 The code in this class was copied from the old KLocale and modified
33 by John Layt (and also Alex Merry) in the KDELIBS 4 to KDE
34 Frameworks 5 transition in 2013.
35
36 Albert Astals Cid is the original author of formatSpelloutDuration()
37 originally named KLocale::prettyFormatDuration().
38
39 Michael Pyne is the original author of formatByteSize().
40
41 Michael Leupold is the original author of formatRelativeDate(()
42 originally part of KFormat::formatDate().
43*/
44
45/**
46 * @class KFormat kformat.h KFormat
47 *
48 * KFormat provides support for formatting numbers and datetimes in
49 * formats that are not supported by QLocale.
50 *
51 * @author John Layt <jlayt@kde.org>,
52 * Michael Pyne <mpyne@kde.org>,
53 * Albert Astals Cid <aacid@kde.org>,
54 *
55 * @short Class for formatting numbers and datetimes.
56 * @since 5.0
57 */
58class KCOREADDONS_EXPORT KFormat final
59{
60 Q_GADGET
61
62public:
63 /**
64 * These binary units are used in KDE by the formatByteSize()
65 * function.
66 *
67 * NOTE: There are several different units standards:
68 * 1) SI (i.e. metric), powers-of-10.
69 * 2) IEC, powers-of-2, with specific units KiB, MiB, etc.
70 * 3) JEDEC, powers-of-2, used for solid state memory sizing which
71 * is why you see flash cards labels as e.g. 4GB. These (ab)use
72 * the metric units. Although JEDEC only defines KB, MB, GB, if
73 * JEDEC is selected all units will be powers-of-2 with metric
74 * prefixes for clarity in the event of sizes larger than 1024 GB.
75 *
76 * Although 3 different dialects are possible this enum only uses
77 * metric names since adding all 3 different names of essentially the same
78 * unit would be pointless. Use BinaryUnitDialect to control the exact
79 * units returned.
80 *
81 * @see BinaryUnitDialect
82 * @see formatByteSize
83 */
84 enum BinarySizeUnits {
85 /// Auto-choose a unit such that the result is in the range [0, 1000 or 1024)
86 DefaultBinaryUnits = -1,
87
88 // The first real unit must be 0 for the current implementation!
89 UnitByte, ///< B 1 byte
90 UnitKiloByte, ///< KiB/KB/kB 1024/1000 bytes.
91 UnitMegaByte, ///< MiB/MB/MB 2^20/10^06 bytes.
92 UnitGigaByte, ///< GiB/GB/GB 2^30/10^09 bytes.
93 UnitTeraByte, ///< TiB/TB/TB 2^40/10^12 bytes.
94 UnitPetaByte, ///< PiB/PB/PB 2^50/10^15 bytes.
95 UnitExaByte, ///< EiB/EB/EB 2^60/10^18 bytes.
96 UnitZettaByte, ///< ZiB/ZB/ZB 2^70/10^21 bytes.
97 UnitYottaByte, ///< YiB/YB/YB 2^80/10^24 bytes.
98 UnitLastUnit = UnitYottaByte,
99 };
100
101 /**
102 * These units are used in KDE by the formatValue() function.
103 *
104 * @see formatValue
105 * @since 5.49
106 */
107 enum class Unit {
108 Other,
109 Bit, ///< "bit"
110 Byte, ///< "B"
111 Meter, ///< "m"
112 Hertz, ///< "Hz"
113 };
114
115 /**
116 * These prefixes are used in KDE by the formatValue()
117 * function.
118 *
119 * IEC prefixes are only defined for integral units of information, e.g.
120 * bits and bytes.
121 *
122 * @see BinarySizeUnits
123 * @see formatValue
124 * @since 5.49
125 */
126 enum class UnitPrefix {
127 /// Auto-choose a unit such that the result is in the range [0, 1000 or 1024)
128 AutoAdjust = -128,
129
130 Yocto = 0, ///< --/-/y 10^-24
131 Zepto, ///< --/-/z 10^-21
132 Atto, ///< --/-/a 10^-18
133 Femto, ///< --/-/f 10^-15
134 Pico, ///< --/-/p 10^-12
135 Nano, ///< --/-/n 10^-9
136 Micro, ///< --/-/ยต 10^-6
137 Milli, ///< --/-/m 10^-3
138 Centi, ///< --/-/c 0.01
139 Deci, ///< --/-/d 0.1
140 Unity, ///< "" 1
141 Deca, ///< --/-/da 10
142 Hecto, ///< --/-/h 100
143 Kilo, ///< Ki/K/k 1024/1000
144 Mega, ///< Mi/M/M 2^20/10^06
145 Giga, ///< Gi/G/G 2^30/10^09
146 Tera, ///< Ti/T/T 2^40/10^12
147 Peta, ///< Pi/P/P 2^50/10^15
148 Exa, ///< Ei/E/E 2^60/10^18
149 Zetta, ///< Zi/Z/Z 2^70/10^21
150 Yotta, ///< Yi/Y/Y 2^80/10^24
151 };
152
153 /**
154 * This enum chooses what dialect is used for binary units.
155 *
156 * Note: Although JEDEC abuses the metric prefixes and can therefore be
157 * confusing, it has been used to describe *memory* sizes for quite some time
158 * and programs should therefore use either Default, JEDEC, or IEC 60027-2
159 * for memory sizes.
160 *
161 * On the other hand network transmission rates are typically in metric so
162 * Default, Metric, or IEC (which is unambiguous) should be chosen.
163 *
164 * Normally choosing DefaultBinaryDialect is the best option as that uses
165 * the user's selection for units. If the user has not selected a preference,
166 * IECBinaryDialect will typically be used.
167 *
168 * @see BinarySizeUnits
169 * @see formatByteSize
170 */
171 enum BinaryUnitDialect {
172 DefaultBinaryDialect = -1, ///< Used if no specific preference
173 IECBinaryDialect, ///< KiB, MiB, etc. 2^(10*n)
174 JEDECBinaryDialect, ///< KB, MB, etc. 2^(10*n)
175 MetricBinaryDialect, ///< SI Units, kB, MB, etc. 10^(3*n)
176 LastBinaryDialect = MetricBinaryDialect,
177 };
178
179 /**
180 * Format flags for formatDuration()
181 * @see DurationFormatOptions
182 */
183 enum DurationFormatOption {
184 DefaultDuration = 0x0, ///< Default formatting in localized 1:23:45 format
185 InitialDuration = 0x1, ///< Default formatting in localized 1h23m45s format
186 ShowMilliseconds = 0x2, ///< Include milliseconds in format, e.g. 1:23:45.678
187 HideSeconds = 0x4, ///< Hide the seconds, e.g. 1:23 or 1h23m, overrides ShowMilliseconds
188 FoldHours = 0x8, ///< Fold the hours into the minutes, e.g. 83:45 or 83m45s, overrides HideSeconds
189 };
190 /**
191 * Stores a combination of #DurationFormatOption values.
192 */
193 Q_DECLARE_FLAGS(DurationFormatOptions, DurationFormatOption)
194 Q_FLAG(DurationFormatOption)
195
196 /**
197 * Constructs a KFormat.
198 *
199 * @param locale the locale to use, defaults to the system locale
200 */
201 explicit KFormat(const QLocale &locale = QLocale());
202
203 /**
204 * Copy constructor
205 */
206 KFormat(const KFormat &other);
207
208 KFormat &operator=(const KFormat &other);
209
210 /**
211 * Destructor
212 */
213 ~KFormat();
214
215 /**
216 * Converts @p size from bytes to the appropriate string representation
217 * using the binary unit dialect @p dialect and the specific units @p units.
218 *
219 * Example:
220 * @code
221 * QString metric, iec, jedec, small;
222 * metric = formatByteSize(1000, 1, KFormat::MetricBinaryDialect, KFormat::UnitKiloByte);
223 * iec = formatByteSize(1024, 1, KFormat::IECBinaryDialect, KFormat::UnitKiloByte);
224 * jedec = formatByteSize(1024, 1, KFormat::JEDECBinaryDialect, KFormat::UnitKiloByte);
225 * small = formatByteSize(100);
226 * // metric == "1.0 kB", iec == "1.0 KiB", jedec == "1.0 KB", small == "100 B"
227 * @endcode
228 *
229 * @param size size in bytes
230 * @param precision number of places after the decimal point to use. KDE uses
231 * 1 by default so when in doubt use 1. Whenever KFormat::UnitByte is used
232 * (either explicitly or autoselected from KFormat::DefaultBinaryUnits),
233 * the fractional part is always omitted.
234 * @param dialect binary unit standard to use. Use DefaultBinaryDialect to
235 * use the localized user selection unless you need to use a specific
236 * unit type (such as displaying a flash memory size in JEDEC).
237 * @param units specific unit size to use in result. Use
238 * DefaultBinaryUnits to automatically select a unit that will return
239 * a sanely-sized number.
240 * @return converted size as a translated string including the units.
241 * E.g. "1.23 KiB", "2 GB" (JEDEC), "4.2 kB" (Metric).
242 * @see BinarySizeUnits
243 * @see BinaryUnitDialect
244 */
245
246 QString formatByteSize(double size,
247 int precision = 1,
248 KFormat::BinaryUnitDialect dialect = KFormat::DefaultBinaryDialect,
249 KFormat::BinarySizeUnits units = KFormat::DefaultBinaryUnits) const;
250
251 /**
252 * Given a number of milliseconds, converts that to a string containing
253 * the localized equivalent, e.g. 1:23:45
254 *
255 * @param msecs Time duration in milliseconds
256 * @param options options to use in the duration format
257 * @return converted duration as a string - e.g. "1:23:45" "1h23m"
258 */
259
260 QString formatDuration(quint64 msecs, KFormat::DurationFormatOptions options = KFormat::DefaultDuration) const;
261
262 /**
263 * Given a number of milliseconds, converts that to a string containing
264 * the localized equivalent to the requested decimal places.
265 *
266 * e.g. given formatDuration(60000), returns "1.0 minutes"
267 *
268 * @param msecs Time duration in milliseconds
269 * @param decimalPlaces Decimal places to round off to, defaults to 2
270 * @return converted duration as a string - e.g. "5.5 seconds" "23.0 minutes"
271 */
272
273 QString formatDecimalDuration(quint64 msecs, int decimalPlaces = 2) const;
274
275 /**
276 * Given a number of milliseconds, converts that to a spell-out string containing
277 * the localized equivalent.
278 *
279 * e.g. given formatSpelloutDuration(60001) returns "1 minute"
280 * given formatSpelloutDuration(62005) returns "1 minute and 2 seconds"
281 * given formatSpelloutDuration(90060000) returns "1 day and 1 hour"
282 *
283 * @param msecs Time duration in milliseconds
284 * @return converted duration as a string.
285 * Units not interesting to the user, for example seconds or minutes when the first
286 * unit is day, are not returned because they are irrelevant. The same applies for
287 * seconds when the first unit is hour.
288 */
289 QString formatSpelloutDuration(quint64 msecs) const;
290
291 /**
292 * Returns a string formatted to a relative date style.
293 *
294 * If the @p date falls within one week before or after the current date
295 * then a relative date string will be returned, such as:
296 * * Yesterday
297 * * Today
298 * * Tomorrow
299 * * Last Tuesday
300 * * Next Wednesday
301 *
302 * If the @p date falls outside this period then the @p format is used.
303 *
304 * @param date the date to be formatted
305 * @param format the date format to use
306 *
307 * @return the date as a string
308 */
309 QString formatRelativeDate(const QDate &date, QLocale::FormatType format) const;
310
311 /**
312 * Returns a string formatted to a relative datetime style.
313 *
314 * If the @p dateTime falls within one week before or after the current date
315 * then a relative date string will be returned, such as:
316 * * Yesterday at 3:00pm
317 * * Today at 3:00pm
318 * * Tomorrow at 3:00pm
319 * * Last Tuesday at 3:00pm
320 * * Next Wednesday at 3:00pm
321 *
322 * If the @p dateTime falls within one hour of the current time.
323 * Then a shorter version is displayed:
324 * * Just a moment ago (for within the same minute)
325 * * 15 minutes ago
326 *
327 * If the @p dateTime falls outside this period then the date is rendered as:
328 * * Monday, 7 September, 2021 at 7:00 PM : date formatted @p format + " at " + time formatted with @p format
329 *
330 * With @p format LongFormat, time format used is set to ShortFormat (to omit timezone and seconds).
331 *
332 * First character is capitalized.
333 *
334 * @param dateTime the date to be formatted
335 * @param format the date format to use
336 *
337 * @return the date as a string
338 */
339 QString formatRelativeDateTime(const QDateTime &dateTime, QLocale::FormatType format) const;
340
341 /**
342 * Converts @p value to the appropriate string representation
343 *
344 * Example:
345 * @code
346 * // sets formatted to "1.0 kbit"
347 * auto formatted = format.formatValue(1000, KFormat::Unit::Bit, 1, KFormat::UnitPrefix::Kilo);
348 * @endcode
349 *
350 * @param value value to be formatted
351 * @param precision number of places after the decimal point to use. KDE uses
352 * 1 by default so when in doubt use 1.
353 * @param unit unit to use in result.
354 * @param prefix specific prefix to use in result. Use UnitPrefix::AutoAdjust
355 * to automatically select an appropriate prefix.
356 * @param dialect prefix standard to use. Use DefaultBinaryDialect to
357 * use the localized user selection unless you need to use a specific
358 * unit type. Only meaningful for KFormat::Unit::Byte, and ignored for
359 * all other units.
360 * @return converted size as a translated string including prefix and unit.
361 * E.g. "1.23 KiB", "2 GB" (JEDEC), "4.2 kB" (Metric), "1.2 kbit".
362 * @see Unit
363 * @see UnitPrefix
364 * @see BinaryUnitDialect
365 * @since 5.49
366 */
367 QString formatValue(double value,
368 KFormat::Unit unit,
369 int precision = 1,
370 KFormat::UnitPrefix prefix = KFormat::UnitPrefix::AutoAdjust,
371 KFormat::BinaryUnitDialect dialect = KFormat::DefaultBinaryDialect) const;
372
373 /**
374 * Converts @p value to the appropriate string representation
375 *
376 * Example:
377 * @code
378 * QString bits, slow, fast;
379 * // sets bits to "1.0 kbit", slow to "1.0 kbit/s" and fast to "12.3 Mbit/s".
380 * bits = format.formatValue(1000, QStringLiteral("bit"), 1, KFormat::UnitPrefix::Kilo);
381 * slow = format.formatValue(1000, QStringLiteral("bit/s");
382 * fast = format.formatValue(12.3e6, QStringLiteral("bit/s");
383 * @endcode
384 *
385 * @param value value to be formatted
386 * @param precision number of places after the decimal point to use. KDE uses
387 * 1 by default so when in doubt use 1.
388 * @param unit unit to use in result.
389 * @param prefix specific prefix to use in result. Use UnitPrefix::AutoAdjust
390 * to automatically select an appropriate prefix.
391 * @return converted size as a translated string including prefix and unit.
392 * E.g. "1.2 kbit", "2.4 kB", "12.3 Mbit/s"
393 * @see UnitPrefix
394 * @since 5.49
395 */
396 QString formatValue(double value, const QString &unit, int precision = 1, KFormat::UnitPrefix prefix = KFormat::UnitPrefix::AutoAdjust) const;
397 /**
398 * Converts @p value to the appropriate string representation.
399 *
400 * Example:
401 * @code
402 * QString iec, jedec, metric;
403 * // Sets iec to "1.0 KiB/s", jedec to "1.0 KB/s" and metric to "1.0 kB/s"
404 * iec = format.formatValue(1024, QStringLiteral("B/s"), 1, KFormat::UnitPrefix::AutoAdjust, KFormat::IECBinaryDialect);
405 * jedec = format.formatValue(1024, QStringLiteral("B/s"), 1, KFormat::UnitPrefix::AutoAdjust, KFormat::JEDECBinaryDialect);
406 * metric = format.formatValue(1000, QStringLiteral("B/s"), 1, KFormat::UnitPrefix::AutoAdjust, KFormat::MetricBinaryDialect);
407 * @endcode
408 *
409 * @param value value to be formatted
410 * @param precision number of places after the decimal point to use. 1 is used by default; when
411 * in doubt use 1
412 * @param unit unit to use in result
413 * @param prefix specific prefix to use in result. Use UnitPrefix::AutoAdjust
414 * to automatically select an appropriate prefix
415 * @param dialect prefix standard to use. Use DefaultBinaryDialect to
416 * use the localized user selection unless you need to use a specific
417 * unit type
418 * @return converted size as a translated string including prefix and unit.
419 * E.g. "1.2 kbit", "2.4 kB", "12.3 Mbit/s"
420 * @see UnitPrefix
421 * @since 5.74
422 */
423 QString formatValue(double value, const QString &unit, int precision, KFormat::UnitPrefix prefix, KFormat::BinaryUnitDialect dialect) const;
424
425private:
426 QSharedDataPointer<KFormatPrivate> d;
427};
428
429#endif // KFORMAT_H
430

source code of kcoreaddons/src/lib/util/kformat.h