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 | |
22 | class QDate; |
23 | class QDateTime; |
24 | |
25 | class 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 | */ |
58 | class KCOREADDONS_EXPORT KFormat final |
59 | { |
60 | Q_GADGET |
61 | |
62 | public: |
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 | |
425 | private: |
426 | QSharedDataPointer<KFormatPrivate> d; |
427 | }; |
428 | |
429 | #endif // KFORMAT_H |
430 | |