public static String binaryPrefix(final Number value)
{
    return prefix(value, 1024, binPrefixes);
} public static String camelize(final String text)
{
    return camelize(text, false);
} public static String capitalize(final String text)
{
    String tmp = text.trim();
    int len = tmp.length();

    if (len == 0)
        return text;

    StringBuilder sb = new StringBuilder(len);

    for (int i = 0; i < len; i++)
    {
        if (Character.isLetter(tmp.charAt(i)))
        {
            Locale locale = currentLocale();
            int lc = i + 1;

            if (i > 0)
            {
                sb.append(tmp.substring(0, i));
            }

            sb.append(tmp.substring(i, lc).toUpperCase(locale));
            sb.append(tmp.substring(lc).toLowerCase(locale));

            break;
        }
    }

    return sb.length() == 0 ? tmp : sb.toString();
} @Expose
public static String decamelize(final String words)
{
    return SPLIT_CAMEL.matcher(words).replaceAll(SPACE);
} public static String duration(final Number seconds)
{
    return duration(seconds, TimeStyle.STANDARD);
} public static String fixLength(final String text, final int charsNum, final char paddingChar)
{
    return fixLength(text, charsNum, paddingChar, false);
} public static String formatCurrency(final Number value)
{
    DecimalFormat decf = context.get().getCurrencyFormat();
    return stripZeros(decf, decf.format(value));
} public static String formatDate(final Date value)
{
    return formatDate(DateFormat.SHORT, value);
} public static String formatDateTime(final Date value)
{
    return context.get().formatDateTime(value);
} public static String formatDecimal(final Number value)
{
    return context.get().formatDecimal(value);
} public static String formatPercent(final Number value)
{
    return context.get().getPercentFormat().format(value);
} public static boolean lossyEquals(final Locale locale, final String source, final String target)
{
    return withinLocale(new Callable<Boolean>()
    {
        @Override
        public Boolean call() throws Exception
        {
            return lossyEquals(source, target);
        }

    }, locale);
} public static String mask(final String mask, final String value)
{
    return maskFormat(mask).format(value);
} public static String metricPrefix(final Number value)
{
    return prefix(value, 1000, metricPrefixes);
} public static String nanoTime(final Number value)
{
    return prefix(value, 1000, nanoTimePrefixes);
} public static String naturalDay(Date then)
{
    return naturalDay(DateFormat.SHORT, then);
} public static String naturalTime(Date duration)
{
    return naturalTime(new Date(), duration);
} public static String ordinal(Number value)
{
    int v = value.intValue();
    int vc = v % 100;

    if (vc > 10 && vc < 14)
        return String.format(ORDINAL_FMT, v, context.get().ordinalSuffix(0));

    return String.format(ORDINAL_FMT, v, context.get().ordinalSuffix(v % 10));
} public static Pace pace(final Number value, final long interval)
{
    double dval = Math.round(value.doubleValue());

    if (dval == 0 || interval == 0)
        return Pace.EMPTY;

    Pace args = null;
    double rate = Math.abs(dval / interval);
    TimeMillis[] intvls = TimeMillis.values();

    for (TimeMillis p : intvls)
    {
        double relativePace = rate * p.millis();
        if (relativePace >= 1)
        {
            args = new Pace(Math.round(relativePace), Accuracy.APROX, p);
            break;
        }
    }

    if (args == null)
    {
        args = new Pace(1, Accuracy.LESS_THAN, intvls[intvls.length - 1]);
    }

    return args;
} public static String paceFormat(final Locale locale, final Number value, final long interval)
{
    return withinLocale(new Callable<String>()
    {
        @Override
        public String call() throws Exception
        {
            return paceFormat(value, interval);
        }
    }, locale);
} public static String pluralize(final Locale locale, final Number number, final PluralizeParams params)
{
    return withinLocale(new Callable<String>()
    {
        @Override
        public String call() throws Exception
        {
            return pluralize(number, params);
        }
    }, locale);
} public static MessageFormat pluralizeFormat(final String template)
{
    String[] tokens = template.split("\\s*\\:{2}\\s*");

    if (tokens.length < 4)
    {
        if (tokens.length == 2)
        {
            tokens = new String[] { "{0}", tokens[1], tokens[0], tokens[1] };
        } else if (tokens.length == 3)
        {
            tokens = new String[] { "{0}", tokens[0], tokens[1], tokens[2] };
        } else
        {
            throw new IllegalArgumentException(String.format(
                    "Template '%s' must declare at least 2 tokens. V.gr. 'one thing::{0} things'", template));
        }
    }

    return pluralizeFormat(tokens[0], Arrays.copyOfRange(tokens, 1, tokens.length));
} public static PrettyTimeFormat prettyTimeFormat()
{
    return context.get().getPrettyTimeFormat();
} @Expose
public static String replaceSupplementary(final String value)
{
    return InterpolationHelper.replaceSupplementary(value, new Replacer()
    {
        public String replace(String in)
        {
            StringBuilder uc = new StringBuilder();

            for (char c : in.toCharArray())
            {
                uc.append("\\\\u");
                uc.append(Integer.toHexString(c).toUpperCase());
            }

            return uc.toString();
        }
    });
} public static Number roundToSignificantFigures(Number num, int precision)
{
    return new BigDecimal(num.doubleValue())
            .round(new MathContext(precision, RoundingMode.HALF_EVEN));
} @Expose
public static String simplify(final String text)
{
    String normalized = java.text.Normalizer.normalize(text, java.text.Normalizer.Form.NFD);
    return COMB_DIACRITICAL.matcher(normalized).replaceAll("");
} @Expose
public static String slugify(final String text)
{
    return slugify(text, SlugifyParams.begin());
} public static String spellBigNumber(final Number value)
{
    BigDecimal v = new BigDecimal(value.toString());

    if (THOUSAND.compareTo(v.abs()) > 0)
        return value.toString();

    boolean isPlural = needPlural(v.unscaledValue().intValue());

    for (BigDecimal bigNum : bigDecExponents.keySet())
        if (bigNum.multiply(THOUSAND).compareTo(v.abs()) > 0)
            return context.get().formatMessage(
                    (isPlural) ? bigDecExponents.get(bigNum) + ".pl" : bigDecExponents.get(bigNum),
                    v.divide(bigNum));

    return value.toString();
} public static String spellDigit(final Number value)
{
    int v = value.intValue();

    if (v < 0 || v > 9)
        return value.toString();

    return context.get().digitStrings(v);
} public static String times(final Number num)
{
    java.text.MessageFormat f = new java.text.MessageFormat(
            context.get().getBundle().getString("times.choice"),
            currentLocale()
            );
    return f.format(new Object[] { Math.abs(num.intValue()) });
} @Expose
public static String titleize(final String text)
{
    return titleize(text, null);
} @Expose
public static String underscore(final String text)
{
    return text.replaceAll("\\s+", "_");
} @Expose
public static String unidecode(final String text)
{
    return Unidecode.decode(text);
} public static String unmask(final String mask, final String value) throws ParseException
{
    return maskFormat(mask).parse(value);
} public static String wordWrap(final String value, final int len)
{
    if (len < 0 || value.length() <= len)
        return value;

    BreakIterator bi = BreakIterator.getWordInstance(currentLocale());
    bi.setText(value);

    return value.substring(0, bi.following(len));
} public class MessageFormat extends ExtendedMessageFormat
{

    private static final long serialVersionUID = -5384364921909539710L;

    private final static Map<String, FormatFactory> formatFactories = loadFormatFactories();

    private static Map<String, FormatFactory> loadFormatFactories()
    {

        Map<String, FormatFactory> factories = new HashMap<String, FormatFactory>();
        ServiceLoader<FormatProvider> ldr = ServiceLoader.load(FormatProvider.class);

        for (FormatProvider provider : ldr)
        {
            registerProvider(factories, provider);
        }

        return factories;

    }

    private static void registerProvider(Map<String, FormatFactory> factories, FormatProvider provider)
    {

        String formatName = provider.getFormatName();
        FormatFactory factory = provider.getFactory();

        if (formatName.indexOf('|') > -1)
        {
            String[] names = formatName.split("\\|");
            for (String name : names)
            {
                factories.put(name, factory);
            }
        } else
        {
            factories.put(formatName, factory);
        }

    }

    public MessageFormat(String pattern)
    {

        super(pattern, formatFactories);

    }

    public MessageFormat(String pattern, Locale locale)
    {

        super(pattern, locale, formatFactories);

    }

    public MessageFormat(String pattern, Locale locale, Map<String, ? extends FormatFactory> registry)
    {

        super(pattern, locale, registry);

    }

    public MessageFormat(String pattern, Map<String, ? extends FormatFactory> registry)
    {

        super(pattern, registry);

    }

    /**
     * Formats the current pattern with the given arguments.
     * 
     * @param arguments
     *            The formatting arguments
     * @return Formatted message
     */
    public String render(Object... arguments)
    {

        return format(arguments);

    }

    /**
     * Formats the current pattern with the given arguments.
     * 
     * @param buffer
     *            The StringBuffer
     * @param arguments
     *            The formatting arguments
     * @return StringBuffer with the formatted message
     */
    public StringBuffer render(StringBuffer buffer, Object... arguments)
    {

        return format(arguments, buffer, null);

    }

} public class Pace
{

    public enum Accuracy
    {
        NONE, APROX, LESS_THAN
    }

    private final long value;
    private final String accuracy;
    private final String timeUnit;

    public static final Pace EMPTY = new Pace(0, Accuracy.NONE, TimeMillis.SECOND);

    public Pace(long value, Accuracy accuracy, TimeMillis timeUnit)
    {
        this.value = value;
        this.accuracy = accuracy.name().toLowerCase();
        this.timeUnit = timeUnit.key();
    }

    public String getAccuracy()
    {
        return accuracy;
    }

    public String getTimeUnit()
    {
        return timeUnit;
    }

    public long getValue()
    {
        return value;
    }

    public String toString()
    {
        return MoreObjects.toStringHelper(this)
                .add("value", value)
                .add("accuracy", accuracy)
                .add("timeUnit", timeUnit)
                .toString();
    }

} public class PrettyTimeFormat extends Format implements FormatProvider
{

    private static final long serialVersionUID = -1398312177396430967L;

    public static FormatFactory factory()
    {

        return new FormatFactory()
        {
            @Override
            public Format getFormat(String name, String args, Locale locale)
            {
                // TODO support unrounded in args?
                return new PrettyTimeFormat(locale);
            }
        };

    }

    private transient PrettyTime prettyTime;

    private final Locale locale;

    public PrettyTimeFormat()
    {
        this(Locale.getDefault());
    }

    public PrettyTimeFormat(Locale locale)
    {
        this.prettyTime = new PrettyTime(locale);
        this.locale = locale;
    }

    public Duration approximateDuration(Date then)
    {
        return prettyTime.approximateDuration(then);
    }

    public List<Duration> calculatePreciseDuration(Date then)
    {
        return prettyTime.calculatePreciseDuration(then);
    }

    public List<TimeUnit> clearUnits()
    {
        return prettyTime.clearUnits();
    }

    /**
     * Convenience format method.
     * 
     * @param ref
     *            The date of reference.
     * @param then
     *            The future date.
     * @return a relative format date as text representation
     */
    public String format(Date ref, Date then)
    {
        return prettyTime.format(DurationHelper.calculateDuration(ref, then, prettyTime.getUnits()));
    }

    /**
     * Convenience format method for precise durations.
     * 
     * @param ref
     *            The date of reference.
     * @param then
     *            The future date.
     * @param precision
     *            The precision to retain in milliseconds.
     * @return a relative format date as text representation or an empty string
     *         if no durations are retained
     */
    public String format(Date ref, Date then, long precision)
    {
        List<Duration> durations = DurationHelper.calculatePreciseDuration(ref, then, prettyTime.getUnits());
        List<Duration> retained = retainPrecision(durations, precision);
        return retained.isEmpty() ? "" : prettyTime.format(retained);
    }

    public String format(Duration duration)
    {
        return prettyTime.format(duration);
    }

    public String format(List<Duration> durations)
    {
        return prettyTime.format(durations);
    }

    @Override
    @SuppressWarnings("unchecked")
    public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos)
    {
        if (Duration.class.isAssignableFrom(obj.getClass()))
        {
            return toAppendTo.append(prettyTime.format((Duration) obj));
        }

        if (Date.class.isAssignableFrom(obj.getClass()))
        {
            return toAppendTo.append(prettyTime.format((Date) obj));
        }

        if (List.class.isAssignableFrom(obj.getClass()))
        {
            return toAppendTo.append(prettyTime.format((List<Duration>) obj));
        }

        if (Number.class.isAssignableFrom(obj.getClass()))
        {
            return toAppendTo.append(prettyTime.format(new Date(((Number) obj).longValue())));
        }

        throw new IllegalArgumentException(String.format("Class %s is not suitable for PrettyTimeFormat",
                obj.getClass()));
    }

    public String formatUnrounded(Date then)
    {
        return prettyTime.formatUnrounded(then);
    }

    public String formatUnrounded(Duration duration)
    {
        return prettyTime.formatUnrounded(duration);
    }

    @Override
    public FormatFactory getFactory()
    {
        return factory();
    }

    public TimeFormat getFormat(TimeUnit unit)
    {
        return prettyTime.getFormat(unit);
    }

    @Override
    public String getFormatName()
    {
        return "prettytime";
    }

    /**
     * Gets the underlying {@link PrettyTime} instance.
     * 
     * @return the underlying {@link PrettyTime} instance.
     */
    public PrettyTime getPrettyTime()
    {
        return prettyTime;
    }

    public List<TimeUnit> getUnits()
    {
        return prettyTime.getUnits();
    }

    @Override
    public Object parseObject(String source, ParsePosition pos)
    {
        throw new UnsupportedOperationException();
    }

    public PrettyTime registerUnit(TimeUnit unit, TimeFormat format)
    {
        return prettyTime.registerUnit(unit, format);
    }

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException
    {
        ois.defaultReadObject();
        this.prettyTime = new PrettyTime(locale);
    }

    private List<Duration> retainPrecision(final List<Duration> durations, final long precision)
    {
        return ImmutableList.copyOf(Iterables.filter(durations, new Predicate<Duration>()
        {
            @Override
            public boolean apply(Duration it)
            {
                return it.getUnit().getMillisPerUnit() >= precision;
            }
        }));
    }

} public enum TimeMillis
{
    SECOND(1000L),
    MINUTE(60000L),
    HOUR(3600000L),
    DAY(86400000L),
    WEEK(604800000L),
    // ideal months
    MONTH(2628000000L);

    private long millis;

    TimeMillis(long millis)
    {
        this.millis = millis;
    }

    public String key()
    {
        return this.name().toLowerCase();
    }

    public long millis()
    {
        return this.millis;
    }
} public enum TimeStyle
{
    STANDARD
    {
        public String format(DefaultContext ctx, boolean neg, int h, int m, int s)
        {

            return String.format("%s%d:%02d:%02d", neg ? '-' : "", h, m, s);

        }
    },
    FRENCH_DECIMAL
    {
        public String format(DefaultContext ctx, boolean neg, int h, int m, int s)
        {

            String r;

            if (h == 0)
            {
                r = (m == 0) ? String.format("%d%s", s, ctx.timeSuffix(2)) :
                        (s == 0) ? String.format("%d%s", m, ctx.timeSuffix(1)) :
                                String.format("%d%s %d%s", m, ctx.timeSuffix(1), s, ctx.timeSuffix(2));
            } else
            {
                r = (m == 0) ?
                        ((s == 0) ? String.format("%d%s", h, ctx.timeSuffix(0)) :
                                String.format("%d%s %d%s", h, ctx.timeSuffix(0), s, ctx.timeSuffix(2))) :
                        (s == 0) ?
                                String.format("%d%s %d%s", h, ctx.timeSuffix(0), m, ctx.timeSuffix(1)) :
                                String.format("%d%s %d%s %d%s", h, ctx.timeSuffix(0), m, ctx.timeSuffix(1), s,
                                        ctx.timeSuffix(2));
            }

            return (neg ? '-' : "") + r;
        }
    };

    public abstract String format(DefaultContext defaultContext, boolean neg, int h, int m, int s);

} public final static class PaceParameters
{
    /**
     * Builder method.
     * 
     * @param one
     *            Format for a single element
     * @return a new pace parameters instance
     */
    public static PaceParameters begin(String one)
    {
        PaceParameters p = new PaceParameters();
        return p.one(one);
    }

    /**
     * Pluralization formats
     */
    public PluralizeParams plural;

    /**
     * The interval of the pace in milliseconds.
     * 
     * @see TimeMillis
     */
    public long interval;

    private PaceParameters()
    {
        //
    }

    public void checkArguments()
    {
        Preconditions.checkArgument(plural != null, "Plural parameters are required");
    }

    public PaceParameters exts(Object... exts)
    {
        this.plural.exts(exts);
        return this;
    }

    public PaceParameters interval(long interval)
    {
        this.interval = interval;
        return this;
    }

    public PaceParameters interval(TimeMillis interval)
    {
        this.interval = interval.millis();
        return this;
    }

    public PaceParameters many(String many)
    {
        this.plural.many(many);
        return this;
    }

    public PaceParameters none(String none)
    {
        this.plural.none(none);
        return this;
    }

    public PaceParameters one(String one)
    {
        this.plural = PluralizeParams.begin(one);
        return this;
    }

    public PaceParameters plural(PluralizeParams plural)
    {
        this.plural = plural;
        return this;
    }
} public final static class PluralizeParams
{
    /**
     * Builder method.
     * 
     * @param one
     *            Format for a single element
     * @return a new pluralize parameters instance
     */
    public static PluralizeParams begin(String one)
    {
        PluralizeParams p = new PluralizeParams();
        return p.one(one);
    }

    /**
     * Format for a single element
     */
    public String one;

    /**
     * Format for many elements
     */
    public String many;

    /**
     * Format for no element
     */
    public String none;

    /**
     * Extended parameters for the specified formats
     */
    public Object[] exts;

    private PluralizeParams()
    {
        //
    }

    public PluralizeParams exts(Object... exts)
    {
        this.exts = exts;
        return this;
    }

    public PluralizeParams many(String many)
    {
        this.many = many;
        return this;
    }

    public PluralizeParams none(String none)
    {
        this.none = none;
        return this;
    }

    public PluralizeParams one(String one)
    {
        this.one = one;
        return this;
    }

} public final static class SlugifyParams
{
    /**
     * Builder method.
     * 
     * @return a new slugify parameters instance
     */
    public static SlugifyParams begin()
    {
        return new SlugifyParams();
    }

    /**
     * Separator slug
     */
    public String separator;

    /**
     * Controls the transformation to lowercase
     */
    public boolean isToLowerCase;

    private SlugifyParams()
    {
        this.separator = DEFAULT_SLUG_SEPARATOR;
        this.isToLowerCase = true;
    }

    public SlugifyParams separator(String separator)
    {
        this.separator = separator;
        return this;
    }

    public SlugifyParams toLowerCase(boolean isToLowerCase)
    {
        this.isToLowerCase = isToLowerCase;
        return this;
    }

}
import static humanize.Humanize.binaryPrefix;
import static humanize.Humanize.camelize;
import static humanize.Humanize.capitalize;
import static humanize.Humanize.decamelize;
import static humanize.Humanize.duration;
import static humanize.Humanize.fixLength;
import static humanize.Humanize.formatCurrency;
import static humanize.Humanize.formatDate;
import static humanize.Humanize.formatDateTime;
import static humanize.Humanize.formatDecimal;
import static humanize.Humanize.formatPercent;
import static humanize.Humanize.lossyEquals;
import static humanize.Humanize.mask;
import static humanize.Humanize.metricPrefix;
import static humanize.Humanize.nanoTime;
import static humanize.Humanize.naturalDay;
import static humanize.Humanize.naturalTime;
import static humanize.Humanize.ordinal;
import static humanize.Humanize.pace;
import static humanize.Humanize.paceFormat;
import static humanize.Humanize.pluralize;
import static humanize.Humanize.pluralizeFormat;
import static humanize.Humanize.prettyTimeFormat;
import static humanize.Humanize.replaceSupplementary;
import static humanize.Humanize.roundToSignificantFigures;
import static humanize.Humanize.simplify;
import static humanize.Humanize.slugify;
import static humanize.Humanize.spellBigNumber;
import static humanize.Humanize.spellDigit;
import static humanize.Humanize.times;
import static humanize.Humanize.titleize;
import static humanize.Humanize.underscore;
import static humanize.Humanize.unidecode;
import static humanize.Humanize.unmask;
import static humanize.Humanize.wordWrap;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import humanize.spi.MessageFormat;
import humanize.time.Pace;
import humanize.time.PrettyTimeFormat;
import humanize.time.TimeMillis;
import humanize.util.Constants.TimeStyle;
import humanize.util.Parameters.PaceParameters;
import humanize.util.Parameters.PluralizeParams;
import humanize.util.Parameters.SlugifyParams;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
import org.junit.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
package humanize;




public class TestHumanize
{

    private static final Locale ES = new Locale("es", "ES");

    private Random rand;

    private Locale defaultLocale;

    @Test(threadPoolSize = 10, invocationCount = 10)
    public void binPrefixTest()
    {
        assertEquals(binaryPrefix(-1), "-1");
        assertEquals(binaryPrefix(0), "0 bytes");
        assertEquals(binaryPrefix(1), "1 bytes");
        assertEquals(binaryPrefix(101), "101 bytes");
        assertEquals(binaryPrefix(1025), "1 KB");
        assertEquals(binaryPrefix(1024), "1 KB");
        assertEquals(binaryPrefix(1536), "1.5 KB");
        assertEquals(binaryPrefix(1048576 * 5), "5 MB");
        assertEquals(binaryPrefix(1073741824L * 2), "2 GB");
        assertEquals(binaryPrefix(1099511627776L * 3), "3 TB");
        assertEquals(binaryPrefix(1325899906842624L), "1.18 PB");

        assertEquals(binaryPrefix(1325899906842624L, ES), "1,18 PB");
    }

    @Test
    public void camelizeTest()
    {

        assertEquals(camelize("bla bla_bla "), "blaBlaBla");
        assertEquals(camelize("  blA_blA  Bla", true), "BlaBlaBla");
        assertEquals(camelize("bla_bla!"), "blaBla!");
        assertEquals(camelize("bla-bla!"), "blaBla!");
        assertEquals(camelize("bla.bla!"), "blaBla!");
        assertEquals(camelize("xxx"), "xxx");
        assertEquals(camelize("___"), "___");
        assertEquals(camelize(" "), " ");
        assertEquals(camelize(" _ _ _"), " _ _ _");
        assertEquals(camelize(""), "");
        assertEquals(camelize("xxx", true), "Xxx");
        assertEquals(camelize("alreadyCamelized"), "alreadyCamelized");

        try
        {
            camelize(null);
            fail("handles null?");
        } catch (NullPointerException ex)
        {

        }

    }

    @Test
    public void capitalizeTest()
    {

        assertEquals(capitalize("hola mundo abc"), "Hola mundo abc");
        assertEquals(capitalize("HOLA mundO AbC"), "Hola mundo abc");
        assertEquals(capitalize("Hola Mundo abC"), "Hola mundo abc");
        assertEquals(capitalize(" Hola Mundo abC  "), "Hola mundo abc");
        assertEquals(capitalize(" (hola Mundo abC)  "), "(Hola mundo abc)");
        assertEquals(capitalize("[HOLA Mundo abC]"), "[Hola mundo abc]");
        assertEquals(capitalize("-HOLA Mundo abC-"), "-Hola mundo abc-");
        assertEquals(capitalize(" ~.-(HOLA Mundo abC)-.~"), "~.-(Hola mundo abc)-.~");
        assertEquals(capitalize(""), "");
        assertEquals(capitalize("* Hola Mundo aBC"), "* Hola mundo abc");
        assertEquals(capitalize("2020"), "2020");

        assertEquals(capitalize("iyi akşamlar", new Locale("tr")), "İyi akşamlar");

        try
        {
            capitalize(null);
            fail("handles null?");
        } catch (NullPointerException ex)
        {

        }

    }

    @Test(threadPoolSize = 10, invocationCount = 10)
    public void decamelizeTest()
    {

        assertEquals(decamelize("lowercase"), "lowercase");
        assertEquals(decamelize("Class"), "Class");
        assertEquals(decamelize("MyClass"), "My Class");
        assertEquals(decamelize("HTML"), "HTML");
        assertEquals(decamelize("PDFLoader"), "PDF Loader");
        assertEquals(decamelize("AString"), "A String");
        assertEquals(decamelize("SimpleXMLParser"), "Simple XML Parser");
        assertEquals(decamelize("GL11Version"), "GL 11 Version");

    }

    @Test
    public void durationFrenchTest()
    {

        assertEquals(duration(3600, TimeStyle.FRENCH_DECIMAL), "1h");