/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.foundationdb.server.types.mcompat.mcasts; import com.foundationdb.server.types.TCast; import com.foundationdb.server.types.TCastBase; import com.foundationdb.server.types.TExecutionContext; import com.foundationdb.server.types.aksql.aktypes.AkInterval; import com.foundationdb.server.types.mcompat.mtypes.MApproximateNumber; import com.foundationdb.server.types.value.ValueSource; import com.foundationdb.server.types.value.ValueTarget; import java.util.EnumMap; import java.util.Map; import java.util.concurrent.TimeUnit; public final class Cast_From_AkIntervalSeconds { public static TCast TO_DOUBLE = new TCastBase(AkInterval.SECONDS, MApproximateNumber.DOUBLE) { @Override protected void doEvaluate(TExecutionContext context, ValueSource source, ValueTarget target) { long raw = source.getInt64(); double result = 0; boolean isNegative; if (raw < 0) { isNegative = true; raw = -raw; } else { isNegative = false; } // we rely here on the fact that the EnumMap sorts entries by ordinal, _and_ that the ordinals // in TimeUnit are organized by small unit -> big. for (Map.Entry<TimeUnit, Double> unitAndMultiplier : placeMultiplierMap.entrySet()) { TimeUnit unit = unitAndMultiplier.getKey(); long asLong = AkInterval.secondsIntervalAs(raw, unit); assert (asLong >= 0) && (asLong < 100) : asLong; raw -= AkInterval.secondsRawFrom(asLong, unit); double multiplier = unitAndMultiplier.getValue(); result += (multiplier * asLong); } if (isNegative) result *= -1d; target.putDouble(result); } }; private static EnumMap<TimeUnit, Double> placeMultiplierMap = createPlaceMultiplierMap(); private static EnumMap<TimeUnit, Double> createPlaceMultiplierMap() { // Desired result is something like 20120802120133.000000 // Nicer format: yyyyMMddHHmmSS.uuuuuu EnumMap<TimeUnit, Double> result = new EnumMap<>(TimeUnit.class); result.put(TimeUnit.MICROSECONDS, 1.0d/1000000.0d); result.put(TimeUnit.SECONDS, 1d); result.put(TimeUnit.MINUTES, 100d); result.put(TimeUnit.HOURS, 10000d); result.put(TimeUnit.DAYS, 1000000d); return result; } }