Skip to content

Instantly share code, notes, and snippets.

@Julien00859
Last active February 16, 2021 22:11
Show Gist options
  • Save Julien00859/a63f6b830547059795689e549045853f to your computer and use it in GitHub Desktop.
Save Julien00859/a63f6b830547059795689e549045853f to your computer and use it in GitHub Desktop.
Parse memory and time value as int
__pycache__/
build/
dist/
*.egg-info/
*.pyc/
import re
from numbers import Number
class Byte(int):
"""
Memory value as byte
>>> Byte(0)
0
>>> Byte(2)
2
>>> Byte('65')
65
>>> Byte('89B')
89
>>> Byte('1k')
1000
>>> Byte('1ki')
1024
>>> Byte('1.5k')
1500
>>> Byte('1.5ki')
1536
>>> Byte('1ki') + Byte('-1k')
24
>>> str(Byte(0))
'0'
>>> str(Byte('70M'))
'70MB'
>>> str(Byte('43Mi'))
'43MiB'
>>> str(Byte('1.5M'))
'1500kB'
"""
__sizes = {
'Ti': 1 << 40,
'T': 1000 ** 4,
'Gi': 1 << 30,
'G': 1000 ** 3,
'Mi': 1 << 20,
'M': 1000 ** 2,
'ki': 1 << 10,
'k': 1000 ** 1,
'': 1,
}
__re = re.compile(r"""^
(?P<float>[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?) # The number as float
(?P<unit>k|M|G|T|ki|Mi|Gi|Ti)?[Bo]? # The unit
$""", re.VERBOSE)
def __new__(cls, x=0):
if isinstance(x, Number):
return super().__new__(cls, x)
match = cls.__re.match(x)
if not match:
raise ValueError("Not a valid byte representation")
return super().__new__(cls, float(match.group('float')) * cls.__sizes[match.group('unit') or ''])
def __str__(self):
if not self:
return "0"
for unit, size in type(self).__sizes.items():
d, m = divmod(self, size)
if not m:
return f"{d}{unit}B"
return super().__str__()
class Time(int):
"""
Time value as second
>>> Time(0)
0
>>> Time(2)
2
>>> Time('34')
34
>>> Time('43s')
43
>>> Time('12m')
720
>>> Time('1.5m')
90
>>> Time('3h')
10800
>>> Time('1d')
86400
>>> Time('2d3h12m43s')
184363
>>> str(Time(0))
'0'
>>> str(Time(12))
'12s'
>>> str(Time('59s'))
'59s'
>>> str(Time('12m'))
'12m'
>>> str(Time('1.5m'))
'1m30s'
>>> str(Time('8h'))
'8h'
>>> str(Time('9h02m'))
'9h2m'
>>> str(Time('4h20m10s'))
'4h20m10s'
>>> str(Time('2d3h12m43s'))
'2d3h12m43s'
"""
__re = re.compile(r"""^(
(?P<second1>[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?)s? # only seconds as float
|(?P<minute1>[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?)m # or minutes as float..
((?P<second2>[0-6]?[0-9])s)? # .. with optionnal seconds in base 60
|(?P<hour1>[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?)h # or hours as float..
((?P<minute2>[0-6]?[0-9])m)? # .. with optionnal minutes in base 60..
((?P<second3>[0-6]?[0-9])s)? # .. and optionnal seconds in base 60
|(?P<day1>[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?)d # or days as float..
((?P<hour2>2[0-4]|[01]?[0-9])h)? # .. with optionnal hours in base 24..
((?P<minute3>[0-6]?[0-9])m)? # .. and optionnal minutes in base 60..
((?P<second4>[0-6]?[0-9])s)? # .. and optionnal seconds in base 60
)$""", re.VERBOSE)
def __new__(cls, x=0):
if isinstance(x, Number):
return super().__new__(cls, x)
match = cls.__re.match(x)
if not match:
raise ValueError("Not a valid time representation")
s1 = float(match.group('second1') or 0)
s2 = float(match.group('second2') or 0)
s3 = float(match.group('second3') or 0)
s4 = float(match.group('second4') or 0)
m1 = float(match.group('minute1') or 0) * 60
m2 = float(match.group('minute2') or 0) * 60
m3 = float(match.group('minute3') or 0) * 60
h1 = float(match.group('hour1') or 0) * 60 * 60
h2 = float(match.group('hour2') or 0) * 60 * 60
d1 = float(match.group('day1') or 0) * 60 * 60 * 24
return super().__new__(cls, d1 + h1 + h2 + m1 + m2 + m3 + s1 + s2 + s3 + s4)
def __str__(self):
if not self:
return "0"
s = ""
for rank, unit in ((60 * 60 * 24, 'd'), (60 * 60, 'h'), (60, 'm'), (1, 's')):
div, mod = divmod(self, rank)
if div:
s += f"{div}{unit}"
self = mod
return s
if __name__ == '__main__':
import sys
if '--test' in sys.argv:
import doctest
doctest.testmod()
[metadata]
name = jmetrics
version = 1.0.3
description = Parse and represent SI units
author = Julien Castiaux
author_email = julien.castiaux@gmail.com
license = MIT
url = https://gist.github.com/Julien00859/a63f6b830547059795689e549045853f
download_url = https://pypi.drlazor.be/metrics
classifiers =
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Operating System :: OS Independent
Programming Language :: Python :: 3 :: Only
Topic :: Software Development :: Libraries :: Python Modules
import setuptools
setuptools.setup(
py_modules=['metrics']
)
@Nauhai
Copy link

Nauhai commented Dec 25, 2020

Ca serait bien d'ajouter les days pour les métriques de temps 👌

@Julien00859
Copy link
Author

Voila qui est fait :)

@Methqphore
Copy link

Ajouter les années, les mois et les millisecondes dans le futur pour le métrique du temps

@Julien00859
Copy link
Author

Pas possible d'ajouter mois et année sans notion de calendrier (une année n'est pas toujours 365 jours, pareil un mois n'est pas toujours 31 jours). Pour les millisecondes c'est impossible étant donné que Time est un sous-type de int et que les secondes sont la plus petite donnée.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment