// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.dataquality.converters;
import java.time.temporal.ChronoUnit;
/**
* this class is used for Converting duration from one unit to another.<br/>
* year<br/>
* month<br/>
* week<br/>
* day<br/>
* hour<br/>
* minute<br/>
* second<br/>
* millisecond<br/>
* input default value is day<br/>
* output default value is hour<br/>
* Created by msjian on 2017-03-28.
*/
public class DurationConverter {
/**
* 1 day = 24 hours.
*/
private static final double num_24 = 24;
/**
* 1 minite = 60 seconds
*/
private static final double num_60 = 60;
/**
* 1 second = 1000 milliseconds.
*/
private static final double num_1000 = 1000;
/**
* 1 year = 365 days.
*/
private static final double num_365 = 365;
/**
* 1 month = 30 days.
*/
private static final double num_30 = 30;
/**
* 1 week = 7 days.
*/
private static final double num_7 = 7;
/**
* 1 year = 52 weeks.
*/
private static final double num_52 = 52;
/**
* 1 year = 12 months.
*/
private static final double num_12 = 12;
public static final ChronoUnit DEFAULT_FROM_UNIT = ChronoUnit.DAYS;
public static final ChronoUnit DEFAULT_TO_UNIT = ChronoUnit.HOURS;
private ChronoUnit fromUnit;
private ChronoUnit toUnit;
/**
* Default constructor, the default from unit is ChronoUnit.DAYS, the default to unit is
* ChronoUnit.HOURS.
*/
public DurationConverter() {
this(DEFAULT_FROM_UNIT, DEFAULT_TO_UNIT);
}
/**
* ConverterDuration Constructor.
*
* @param from - the from ChronoUnit, default value is ChronoUnit.DAYS.
* @param to - the to ChronoUnit, default value is ChronoUnit.HOURS.
*/
public DurationConverter(ChronoUnit from, ChronoUnit to) {
this.fromUnit = from == null ? DEFAULT_FROM_UNIT : from;
this.toUnit = to == null ? DEFAULT_TO_UNIT : to;
}
/**
* convert the value from fromUnit type to toUnit type.
*
* @param value
* @return long
*/
public double convert(double value) {
if (Double.isNaN(value)) {
return value;
}
if (Double.compare(Double.MAX_VALUE, value) == 0 || Double.compare(Double.MIN_VALUE, value) == 0) {
return value;
}
if (this.fromUnit.equals(this.toUnit)) {
return value;
}
// get the days first, then use it as base to convert to the target value.
double days = 0;
switch (this.fromUnit) {
case MILLIS:
days = value / num_24 / num_60 / num_60 / num_1000;
break;
case SECONDS:
days = value / num_24 / num_60 / num_60;
break;
case MINUTES:
days = value / num_24 / num_60;
break;
case HOURS:
days = value / num_24;
break;
case DAYS:
days = value;
break;
case YEARS:
days = value * num_365;
break;
case MONTHS:
days = value * num_30;
break;
case WEEKS:
days = value * num_7;
break;
default:
break;
}
switch (this.toUnit) {
case MILLIS:
return getExactDays(value, days) * num_24 * num_60 * num_60 * num_1000;
case SECONDS:
return getExactDays(value, days) * num_24 * num_60 * num_60;
case MINUTES:
return getExactDays(value, days) * num_24 * num_60;
case HOURS:
return getExactDays(value, days) * num_24;
case DAYS:
return getExactDays(value, days);
case YEARS:
return days / num_365;
case MONTHS:
return days / num_30;
case WEEKS:
return days / num_7;
default:
break;
}
return value;
}
/**
* get the days more exactly with what we want. because:
* 1 year = 365 days = 12 months (!= 12 * 30)
* 1 month = 30 days
* 1 week = 7 days
*
* for example:
* 13 months = 1*365+1*30 != 13*30.
* 5 weeks = 5*7 != 1*30+1*7
*
* @param value
* @param days
* @return
*/
protected double getExactDays(double value, double days) {
if (this.fromUnit == ChronoUnit.MONTHS) {
int year = (int) (value / num_12);
int month = (int) (value % num_12);
return year * num_365 + month * num_30;
} else if (this.fromUnit == ChronoUnit.WEEKS) {
int year = (int) (value / num_52);
int week = (int) (value % num_52);
return year * num_365 + week * num_7;
}
return days;
}
}