import java.util.List; import java.util.ArrayList; public class NumberFormatter { public static void main (String[] args) throws Exception { // Format duration System.out.println(formatNumber(1234567890, new long[] { 1000, 60, 60, 60, 24 }, new String[] { " ms", " ms", " second", " seconds", " minute", " minutes", " hour", " hours", " day", " days" })); // Format file size System.out.println(formatNumber(1234567890, new long[] { 1024, 1024, 1024 }, new String[] { "b", "b", "K", "K", "M", "M", "G", "G" })); } public static String formatNumber (long value, long[] limits, String[] labels) { List parts = new ArrayList(); if (value > 0) { dissectNumber(parts, value, limits, labels, 0); } else if (value == 0) { parts.add("0"); } else { parts.add("- "); parts.add(formatNumber(-value, limits, labels)); } StringBuffer text = new StringBuffer(); String[] textParts = (String[]) parts.toArray(new String[0]); for (int i = 0, len = textParts.length; i < len; i += 2) { if (i > 0) { text.append(", "); } text.append(textParts[i]).append(textParts[i + 1]); } return String.valueOf(text); } protected static void dissectNumber (List parts, long value, long[] limits, String[] labels, int depth) { int labelIndex = depth * 2; if (depth == limits.length) { parts.add(0, labels[(value == 1) ? labelIndex : (labelIndex + 1)]); parts.add(0, String.valueOf(value)); } else { long limit = limits[depth]; long hi = value / limit; long lo = value % limit; if (lo > 0) { parts.add(0, labels[(lo == 1) ? labelIndex : (labelIndex + 1)]); parts.add(0, String.valueOf(lo)); } if (hi > 0) { dissectNumber(parts, hi, limits, labels, depth + 1); } } } } ...