/*
* [Age.java]
*
* Summary: Calculate Age from birthdate.
*
* Copyright: (c) 2005-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
*
* Licence: This software may be copied and used freely for any purpose but military.
* http://mindprod.com/contact/nonmil.html
*
* Requires: JDK 1.8+
*
* Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
*
* Version History:
* 1.0 2005-03-19
*/
package com.mindprod.htmlmacros.macro;
import com.mindprod.common18.BigDate;
import com.mindprod.fastcat.FastCat;
import java.text.DecimalFormat;
import static java.lang.System.*;
/**
* Calculate Age from birthdate.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.0 2005-03-19
* @see com.mindprod.common18.Age
* @since 2005-03-19
*/
@SuppressWarnings( { "UnusedDeclaration" } )
public final class Age extends Macro
{
/**
* how to use the macro
*/
private static final String USAGE = "\nAge macro needs date yyyy-mm-dd[BC] [on yyyy-mm-ddAD] [centuries/decades/years/months/days/puredays] Trailing BC ok, but not missing mm-dd";
/**
* Template for comma.
*/
private static final DecimalFormat DF0 = new DecimalFormat( "###,##0" );
/**
* guts of Age macro expansion
*
* @param birthDate person's birth date whose age you want expanded
* @param onDate usually today, date on which to compute the age.
* @param granularity -3 = centuries, -2= decades, -1 = years without wording 0=years 1=months 2=days
*
* @return age in spelled out in centuries, decades, years, months, days as requsened
*/
private String expand( BigDate birthDate, BigDate onDate, int granularity )
{
// usually OnDate >= birthDate , but for future elapsed time to some future date, OnDate < birthDate;
final int[] ymd = BigDate.age( birthDate, onDate );
int ageInYears = ymd[ 0 ];
int ageInDecades = ( ageInYears + 5 ) / 10;
int ageInCenturies = ( ageInYears + 50 ) / 100;
int ageInMonths = ymd[ 1 ];
int ageInDays = ymd[ 2 ];
switch ( granularity )
{
case -3:
ageInDecades = 0;
ageInYears = 0;
ageInMonths = 0;
ageInDays = 0;
break;
case -2:
ageInCenturies = 0;
ageInYears = 0;
ageInMonths = 0;
ageInDays = 0;
break;
case -1:
case 0:
ageInCenturies = 0;
ageInDecades = 0;
ageInMonths = 0;
ageInDays = 0;
break;
case 1:
ageInCenturies = 0;
ageInDecades = 0;
ageInDays = 0;
break;
case 2:
ageInCenturies = 0;
ageInDecades = 0;
break;
case 3:
ageInCenturies = 0;
ageInDecades = 0;
ageInYears = 0;
ageInMonths = 0;
ageInDays = onDate.getOrdinal() - birthDate.getOrdinal();
break;
}
final FastCat sb = new FastCat( 16 );
if ( ageInCenturies != 0 )
{
sb.append( "" );
sb.append( DF0.format( ageInCenturies ) );
sb.append( " " );
if ( ageInCenturies > 1 )
{
sb.append( "centuries" );
}
else
{
sb.append( "century" );
}
}
if ( ageInDecades != 0 )
{
sb.append( "" );
sb.append( DF0.format( ageInDecades ) );
sb.append( " decade" );
if ( ageInDecades > 1 )
{
sb.append( "s" );
}
}
if ( ageInYears != 0 )
{
sb.append( "" );
sb.append( DF0.format( ageInYears ) );
sb.append( "" );
if ( granularity != -1 )
{
sb.append( " year" );
if ( ageInYears > 1 )
{
sb.append( "s" );
}
}
}
if ( ageInMonths != 0 )
{
if ( ageInYears != 0 )
{
if ( ageInDays != 0 )
{
sb.append( ", " );
}
else
{
sb.append( " and " );
}
}
sb.append( "" );
sb.append( ageInMonths );
sb.append( " month" );
if ( ageInMonths > 1 )
{
sb.append( "s" );
}
}
if ( ageInDays != 0 )
{
if ( ageInYears != 0 || ageInMonths != 0 )
{
sb.append( " and " );
}
sb.append( "" );
sb.append( ageInDays );
sb.append( " day" );
if ( ageInDays > 1 )
{
sb.append( "s" );
}
}
return sb.toString();
}
/**
* Generate Age from birthdate . expands to age in years. or
* Date can be in future.
* days = year month days
* puredate = ordinal diff days.
*
* @param parms date as ISO string.
* @param quiet true if want output suppressed.
* @param verbose @return expanded macro text
*/
public String expandMacro( String[] parms,
final boolean quiet, final boolean verbose )
{
if ( !quiet )
{
out.print( "A" );
}
if ( !( 1 <= parms.length && parms.length <= 4 ) )
{
throw new IllegalArgumentException( USAGE );
}
try
{
final BigDate birthDate = new BigDate( parms[ 0 ] );
final BigDate onDate;
final int granularityParmIndex;
if ( parms.length > 2 && parms[ 1 ].equals( "on" ) )
{
onDate = new BigDate( parms[ 2 ] );
granularityParmIndex = 3;
}
else
{
onDate = Global.TODAY;
granularityParmIndex = 1;
}
final int granularity;
if ( parms.length > granularityParmIndex )
{
final String units = parms[ granularityParmIndex ];
if ( units.equalsIgnoreCase( "centuries" ) )
{
granularity = -3;
}
else if ( units.equalsIgnoreCase( "decades" ) )
{
granularity = -2;
}
else if ( units.equalsIgnoreCase( "years" ) )
{
granularity = 0;
}
else if ( units.equalsIgnoreCase( "months" ) )
{
granularity = 1;
}
else if ( units.equalsIgnoreCase( "days" ) )
{
granularity = 2;
}
else if ( units.equalsIgnoreCase( "puredays" ) )
{
granularity = 3;
}
else
{
throw new IllegalArgumentException( USAGE );
}
}
else
{
granularity = -1; // years without wording
}
return expand( birthDate, onDate, granularity );
}
catch ( StringIndexOutOfBoundsException e )
{
throw new IllegalArgumentException( USAGE );
}
catch ( NumberFormatException e )
{
throw new IllegalArgumentException( USAGE );
}
}
}