/** * Returns the date in seconds. * * @return seconds */ final BigDecimal seconds() { int z = tz; if (z == Short.MAX_VALUE) { // [CG] XQuery, DateTime: may be removed final long n = System.currentTimeMillis(); z = Calendar.getInstance().getTimeZone().getOffset(n) / 60000; } return (sec == null ? BigDecimal.ZERO : sec) .add(BigDecimal.valueOf(Math.max(0, hou) * 3600 + Math.max(0, min) * 60 - z * 60)); }
/** * Adds the time zone to the specified token builder. * * @param tb token builder */ void zone(final TokenBuilder tb) { if (tz == Short.MAX_VALUE) return; if (tz == 0) { tb.add('Z'); } else { tb.add(tz > 0 ? '+' : '-'); prefix(tb, Math.abs(tz) / 60, 2); tb.add(':'); prefix(tb, Math.abs(tz) % 60, 2); } }
/** * Adds the time to the specified token builder. * * @param tb token builder */ final void time(final TokenBuilder tb) { if (sec.remainder(DAYSECONDS).signum() == 0) return; tb.add('T'); final long h = hou(); if (h != 0) { tb.addLong(Math.abs(h)); tb.add('H'); } final long m = min(); if (m != 0) { tb.addLong(Math.abs(m)); tb.add('M'); } final BigDecimal sc = sec(); if (sc.signum() == 0) return; tb.add(Token.chopNumber(Token.token(sc.abs().toPlainString()))).add('S'); }
/** * Adds the date to the specified token builder. * * @param tb token builder */ final void date(final TokenBuilder tb) { tb.add('P'); final long y = yea(); if (y != 0) { tb.addLong(Math.abs(y)); tb.add('Y'); } final long m = mon(); if (m != 0) { tb.addLong(Math.abs(m)); tb.add('M'); } final long d = day(); if (d != 0) { tb.addLong(Math.abs(d)); tb.add('D'); } }
/** * Adds/subtracts the specified yearMonth duration. * * @param dur duration * @param plus plus/minus flag * @param ii input info * @throws QueryException query exception */ final void calc(final YMDur dur, final boolean plus, final InputInfo ii) throws QueryException { final long m = plus ? dur.mon : -dur.mon; final long mn = mon + m; mon = (byte) mod(mn, 12); yea += div(mn, 12); day = (byte) Math.min(dpm(yea, mon) - 1, day); if (yea <= MIN_YEAR || yea > MAX_YEAR) throw YEARRANGE_X.get(ii, yea); }
/** * Adds the specified dayTime duration. * * @param add value to be added */ private void add(final BigDecimal add) { // normalized modulo: sc % 60 vs. (-sc + sc % 60 + 60 + sc) % 60 final BigDecimal sc = sec().add(add); sec = sc.signum() >= 0 ? sc.remainder(BD60) : sc.negate().add(sc.remainder(BD60)).add(BD60).add(sc).remainder(BD60); final long mn = Math.max(min(), 0) + div(sc.longValue(), 60); min = (byte) mod(mn, 60); final long ho = Math.max(hou, 0) + div(mn, 60); hou = (byte) mod(ho, 24); final long da = div(ho, 24); final long[] ymd = ymd(days().add(BigDecimal.valueOf(da))); yea = ymd[0]; mon = (byte) ymd[1]; day = (byte) ymd[2]; }
/** * Compiles the filter expression, excluding the root node. * * @param ctx query context * @return compiled expression */ private Expr opt(final QueryContext ctx) { // evaluate return type final SeqType t = root.type(); // determine number of results and type final long s = root.size(); if (s != -1) { if (pos != null) { size = Math.max(0, s + 1 - pos.min) - Math.max(0, s - pos.max); } else if (last) { size = s > 0 ? 1 : 0; } // no results will remain: return empty sequence if (size == 0) return optPre(null, ctx); type = SeqType.get(t.type, size); } else { type = SeqType.get(t.type, t.zeroOrOne() ? Occ.ZERO_ONE : Occ.ZERO_MORE); } // no numeric predicates.. use simple iterator if (!super.has(Flag.FCS)) return new IterFilter(this); // one single position() or last() function specified: return single value if (preds.length == 1 && (last || pos != null) && root.isValue() && t.one() && (last || pos.min == 1 && pos.max == 1)) return optPre(root, ctx); // only choose deterministic and context-independent offsets; e.g., skip: // (1 to 10)[random:integer(10)] or (1 to 10)[.] boolean off = false; if (preds.length == 1) { final Expr p = preds[0]; final SeqType st = p.type(); off = st.type.isNumber() && st.zeroOrOne() && !p.has(Flag.CTX) && !p.has(Flag.NDT); if (off) type = SeqType.get(type.type, Occ.ZERO_ONE); } // iterator for simple numeric predicate return off || useIterator() ? new IterPosFilter(this, off) : this; }
/** * Adjusts the timezone. * * @param zone timezone * @param spec indicates if zone has been specified (may be {@code null}) * @param ii input info * @throws QueryException query exception */ void tz(final DTDur zone, final boolean spec, final InputInfo ii) throws QueryException { final short t; if (spec && zone == null) { t = Short.MAX_VALUE; } else { if (zone == null) { final Calendar c = Calendar.getInstance(); t = (short) ((c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET)) / 60000); } else { t = (short) (zone.min() + zone.hou() * 60); if (zone.sec().signum() != 0) throw ZONESEC_X.get(ii, zone); if (Math.abs(t) > 60 * 14 || zone.day() != 0) throw INVALZONE_X.get(ii, zone); } // change time if two competing time zones exist if (tz != Short.MAX_VALUE) add(BigDecimal.valueOf(60L * (t - tz))); } tz = t; }
@Override public byte[] string(final InputInfo ii) { final TokenBuilder tb = new TokenBuilder(); final boolean ymd = yea != Long.MAX_VALUE; if (ymd) { if (yea <= 0) tb.add('-'); prefix(tb, Math.abs(yea()), 4); tb.add('-'); prefix(tb, mon(), 2); tb.add('-'); prefix(tb, day(), 2); } if (hou >= 0) { if (ymd) tb.add('T'); prefix(tb, hou(), 2); tb.add(':'); prefix(tb, min(), 2); tb.add(':'); if (sec.intValue() < 10) tb.add('0'); tb.addExt(Token.chopNumber(Token.token(sec().abs().toPlainString()))); } zone(tb); return tb.finish(); }
/** * Rounds values. * * @param qc query context * @param even half-to-even flag * @return number * @throws QueryException query exception */ ANum round(final QueryContext qc, final boolean even) throws QueryException { final ANum num = toNumber(exprs[0], qc); final long p = exprs.length == 1 ? 0 : Math.max(Integer.MIN_VALUE, toLong(exprs[1], qc)); return num == null ? null : p > Integer.MAX_VALUE ? num : num.round((int) p, even); }
@Override void calcSize(final long[] minMax) { minMax[0] = Math.min(minMax[0], 1); }
/** * Returns a day count. * * @return days */ final BigDecimal days() { final long y = yea == Long.MAX_VALUE ? 1 : yea; return days(y + ADD_NEG, Math.max(mon, 0), Math.max(day, 0)); }