package org.basex.query.item;
import static org.basex.query.QueryText.*;
import static org.basex.query.util.Err.*;
import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.basex.query.QueryException;
import org.basex.query.util.Err;
import org.basex.util.InputInfo;
import org.basex.util.Token;
import org.basex.util.TokenBuilder;
/**
* DayTime Duration item.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class DTd extends Dur {
/** DayTime pattern. */
private static final Pattern DUR = Pattern.compile("(-?)P(([0-9]+)D)?" +
"(T(([0-9]+)H)?(([0-9]+)M)?(([0-9]+(\\.[0-9]+)?)S)?)?");
/**
* Constructor.
* @param d duration item
*/
DTd(final Dur d) {
super(AtomType.DTD);
sc = d.sc == null ? BigDecimal.valueOf(0) : d.sc;
}
/**
* Timezone constructor.
* @param shift shift value
*/
public DTd(final int shift) {
super(AtomType.DTD);
sc = BigDecimal.valueOf(shift * 60L);
}
/**
* Constructor.
* @param it duration item
* @param a duration to be added/subtracted
* @param p plus/minus flag
*/
public DTd(final DTd it, final DTd a, final boolean p) {
this(it);
sc = p ? sc.add(a.sc) : sc.subtract(a.sc);
}
/**
* Constructor.
* @param it duration item
* @param f factor
* @param m multiplication flag
* @param ii input info
* @throws QueryException query exception
*/
public DTd(final Dur it, final double f, final boolean m, final InputInfo ii)
throws QueryException {
this(it);
if(Double.isNaN(f)) DATECALC.thrw(ii, description(), f);
if(m ? f == 1 / 0d || f == -1 / 0d : f == 0)
DATEZERO.thrw(ii, description());
sc = sc.multiply(BigDecimal.valueOf(m ? f : 1 / f));
if(Math.abs(sc.doubleValue()) < 1E-13) sc = BigDecimal.valueOf(0);
}
/**
* Constructor.
* @param dat date item
* @param sub date to be subtracted
*/
public DTd(final Date dat, final Date sub) {
super(AtomType.DTD);
final long d1 = dat.days();
final BigDecimal s1 = dat.seconds();
final long d2 = sub.days();
final BigDecimal s2 = sub.seconds();
sc = BigDecimal.valueOf((d1 - d2) * DAYSECONDS).add(s1.subtract(s2));
}
/**
* Constructor.
* @param v value
* @param ii input info
* @throws QueryException query exception
*/
DTd(final byte[] v, final InputInfo ii) throws QueryException {
super(AtomType.DTD);
final String val = Token.string(v).trim();
final Matcher mt = DUR.matcher(val);
if(!mt.matches() || val.endsWith("P") || val.endsWith("T"))
dateErr(v, XDTD, ii);
final long d = mt.group(2) != null ? Token.toInt(mt.group(3)) : 0;
final long h = mt.group(5) != null ? Token.toInt(mt.group(6)) : 0;
final long n = mt.group(7) != null ? Token.toInt(mt.group(8)) : 0;
final double s = mt.group(9) != null ?
Token.toDouble(Token.token(mt.group(10))) : 0;
sc = BigDecimal.valueOf(d * DAYSECONDS + h * 3600 + n * 60);
sc = sc.add(BigDecimal.valueOf(s));
if(!mt.group(1).isEmpty()) sc = sc.negate();
}
/**
* Returns the date and time.
* @return year
*/
public BigDecimal dtd() {
return sc;
}
@Override
public byte[] string(final InputInfo ii) {
final TokenBuilder tb = new TokenBuilder();
if(sc.signum() < 0) tb.add('-');
tb.add('P');
if(day() != 0) { tb.addLong(Math.abs(day())); tb.add('D'); }
if(sc.remainder(BigDecimal.valueOf(DAYSECONDS)).signum() != 0) {
tb.add('T');
if(hou() != 0) { tb.addLong(Math.abs(hou())); tb.add('H'); }
if(min() != 0) { tb.addLong(Math.abs(min())); tb.add('M'); }
if(sec().signum() != 0) { tb.add(sc()); tb.add('S'); }
}
if(sc.signum() == 0) tb.add("T0S");
return tb.finish();
}
@Override
public int diff(final InputInfo ii, final Item it) throws QueryException {
if(it.type != type) Err.diff(ii, it, this);
return sc.subtract(((Dur) it).sc).signum();
}
}