Created
November 21, 2014 17:50
-
-
Save gregpinero/614b6af033bc292e5839 to your computer and use it in GitHub Desktop.
Python Formatting Functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import re | |
| import datetime | |
| import math | |
| def format_timeinterval(start, end=None): | |
| if not end: | |
| end = datetime.now() | |
| return format_timedelta(end - start) | |
| def format_secondsdelta(seconds): | |
| """"""Useful for database time differences"""""" | |
| return format_timedelta(datetime.timedelta(0, seconds, 0)) | |
| def format_timedelta(td): | |
| if td.days > 365: | |
| return _format_num(td.days / 365.0, 'yrs') | |
| if td.days > 30: | |
| return _format_num(td.days / 30.0, 'mos') | |
| if td.days > 7: | |
| return _format_num(td.days / 7.0, 'wks') | |
| if td.days > 0: | |
| return _format_num(td.days + td.seconds / (60.0 * 60.0 * 24.0), 'days') | |
| if td.seconds > 3600: | |
| return _format_num(td.seconds / 3600.0, 'hrs') | |
| if td.seconds > 60: | |
| return _format_num(td.seconds / 60.0, 'min') | |
| if td.seconds > 0: | |
| return _format_num(td.seconds + td.microseconds / 1000000.0, 'sec') | |
| return _format_num(td.microseconds / 1000.0, 'msec') | |
| def _format_num(val, units): | |
| s = ""%.1f %s"" % (val, units) | |
| # HACK works but ugly | |
| return s.replace('.0 ', ' ') | |
| def commas(value): | |
| return """".join(commafy(value)) | |
| def commafy(s): | |
| if s.startswith('-'): | |
| s = s[1:] | |
| yield ""-"" | |
| pieces = str(s).split(""."") | |
| n = len(pieces[0]) | |
| for i in range(0, n): | |
| if (n - i) % 3 or not i: | |
| yield pieces[0][i] | |
| else: | |
| yield "","" | |
| yield pieces[0][i] | |
| if len(pieces) > 1: | |
| yield ""."" + pieces[1] | |
| # TODO make this fancy like C# formatting... | |
| def format(value, fmt): | |
| """"""Format a numeric value supporting things | |
| like commas, parens for negative values and | |
| special cases for zeros. Format is: | |
| 'n[cpzZ]%' ex: '2c', '0cpz', '1%' | |
| n - number of decimals | |
| c - use commas | |
| p - wrap negative numbers in parenthesis | |
| z - use a ' ' for zero values | |
| Z - use a '-' for zero values | |
| K - convert to thousands and add 'K' suffix | |
| M - convert to millions and add 'M' suffix | |
| B - convert to billions and add 'B' suffix | |
| S - convert to shorter of KMB formats | |
| % - scale by 100 and add a percent sign at the end (unless z/Z) | |
| """""" | |
| # first ensure we have a reasonable value | |
| try: | |
| value = float(value) | |
| except: | |
| return value or '' | |
| # now format it | |
| try: | |
| m = re.match(r'^(\d)[cpzZKMBS%]{0,4}$', fmt) | |
| if not m: | |
| return value | |
| # handle zero specially, if requested | |
| if value == 0: | |
| if 'z' in fmt: | |
| return '' | |
| elif 'Z' in fmt: | |
| return '-' | |
| # scale if using %, K, M or B formats | |
| suffix = '' | |
| factor = { '%': 1e2, 'K': 1e-3, 'M': 1e-6, 'B': 1e-9 } | |
| for k in factor.keys(): | |
| if k in fmt: | |
| suffix = k | |
| value *= factor[k] | |
| break | |
| # use parens for negative values | |
| parens = False | |
| if 'p' in fmt and value < 0: | |
| value = -value | |
| parens = True | |
| # format the number to the specified number of decimal places | |
| s = '%%.%sf' % m.group(1) | |
| val = s % value | |
| # fix up with commas | |
| if 'c' in fmt: | |
| val = commas(val) | |
| # wrap in parens | |
| if parens: | |
| val = '(%s)' % val | |
| elif 'p' in fmt: | |
| # pad positive numbers so the last digit lines up better | |
| val = '%s' % val | |
| val += suffix | |
| return val | |
| except Exception, e: | |
| return value or '' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment