2023-01-11 20:02:36 +01:00
|
|
|
from enum import Enum
|
|
|
|
|
|
|
|
|
|
|
|
def test():
|
|
|
|
for num_bytes in [0, 1, 128, 512, 1024, 4096, 75 * 1000, 750 * 1000, 850 * 1000, 1111 * 1000]:
|
|
|
|
print(f'{num_bytes} bytes = {DataUnitConverter.to_unit_auto_str(num_bytes)}')
|
|
|
|
|
|
|
|
|
|
|
|
class DataUnitConverter:
|
2023-03-18 15:24:10 +01:00
|
|
|
"""
|
|
|
|
A class to convert between data units.
|
|
|
|
|
|
|
|
Example: 1.000.000 B == 1 MB
|
|
|
|
|
|
|
|
The main purpose is to convert a number with many digits
|
|
|
|
to a "larger" unit so that the number is shorter
|
|
|
|
and more readable.
|
|
|
|
"""
|
|
|
|
|
2023-01-11 20:02:36 +01:00
|
|
|
class DataUnit(Enum):
|
|
|
|
B = 'B'
|
|
|
|
KB = 'KB'
|
|
|
|
MB = 'MB'
|
|
|
|
GB = 'GB'
|
|
|
|
TB = 'TB'
|
|
|
|
|
|
|
|
# Units sorted from small to large.
|
|
|
|
_unit_dict: dict[DataUnit, int] = {
|
|
|
|
DataUnit.B: 1,
|
|
|
|
DataUnit.KB: 1024,
|
|
|
|
DataUnit.MB: 1024 * 1024,
|
|
|
|
DataUnit.GB: 1024 * 1024 * 1024,
|
|
|
|
DataUnit.TB: 1024 * 1024 * 1024 * 1024,
|
|
|
|
}
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def to_bytes(cls, num: int, unit: DataUnit) -> int:
|
|
|
|
return num * cls._unit_dict[unit]
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def to_unit(cls, num_bytes: int, unit: DataUnit = DataUnit.GB) -> float:
|
|
|
|
return round(num_bytes / cls._unit_dict[unit], 3)
|
|
|
|
|
2023-03-29 17:48:51 +02:00
|
|
|
@classmethod
|
|
|
|
def to_unit_str(cls, num_bytes: int, unit: DataUnit = DataUnit.GB) -> str:
|
|
|
|
value = round(num_bytes / cls._unit_dict[unit], 3)
|
|
|
|
return cls.to_str(value, unit)
|
|
|
|
|
2023-01-11 20:02:36 +01:00
|
|
|
@classmethod
|
2023-01-12 16:28:18 +01:00
|
|
|
def to_unit_auto(cls, num_bytes: int) -> tuple[float, DataUnit]:
|
2023-01-11 20:02:36 +01:00
|
|
|
for unit, factor in cls._unit_dict.items():
|
|
|
|
converted = cls.to_unit(num_bytes, unit)
|
|
|
|
if converted <= 999:
|
|
|
|
return converted, unit
|
|
|
|
|
|
|
|
return num_bytes, cls.DataUnit.B
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def to_unit_auto_str(cls, num_bytes: int) -> str:
|
|
|
|
value, unit = cls.to_unit_auto(num_bytes)
|
2023-03-29 17:48:51 +02:00
|
|
|
return cls.to_str(value, unit)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def to_str(cls, value: float, unit: DataUnit):
|
2023-01-11 20:02:36 +01:00
|
|
|
return f'{value} {unit.value}'
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
test()
|