blob: ce8c1083f97df48036425bf7a1180721bf259e93 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.carbondata.core.preagg;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import org.apache.carbondata.common.logging.LogServiceFactory;
import org.apache.carbondata.core.constants.CarbonCommonConstants;
import org.apache.carbondata.core.util.CarbonProperties;
import org.apache.log4j.Logger;
/**
* class for applying time-series udf
*/
public class TimeSeriesUDF {
private static final Logger LOGGER =
LogServiceFactory.getLogService(TimeSeriesUDF.class.getName());
public final List<String> TIMESERIES_FUNCTION = new ArrayList<>();
// thread local for keeping calender instance
private ThreadLocal<Calendar> calenderThreadLocal = new ThreadLocal<>();
/**
* singleton instance
*/
public static final TimeSeriesUDF INSTANCE = new TimeSeriesUDF();
private TimeSeriesUDF() {
initialize();
}
/**
* Below method will be used to apply udf on data provided
* Method will work based on below logic.
* Data: 2016-7-23 01:01:30,10
* Year Level UDF will return: 2016-1-1 00:00:00,0
* Month Level UDF will return: 2016-7-1 00:00:00,0
* Day Level UDF will return: 2016-7-23 00:00:00,0
* Hour Level UDF will return: 2016-7-23 01:00:00,0
* Minute Level UDF will return: 2016-7-23 01:01:00,0
* Second Level UDF will return: 2016-7-23 01:01:30,0
* If function does not match with any of the above functions
* it will throw IllegalArgumentException
*
* @param data timestamp data
* @param function time series function name
* @return data after applying udf
*/
public Timestamp applyUDF(Timestamp data, String function) {
if (null == data) {
return data;
}
initialize();
Calendar calendar = calenderThreadLocal.get();
calendar.clear();
calendar.setTimeInMillis(data.getTime());
TimeSeriesFunctionEnum timeSeriesFunctionEnum =
TimeSeriesFunctionEnum.valueOf(function.toUpperCase());
switch (timeSeriesFunctionEnum) {
case SECOND:
calendar.set(Calendar.MILLISECOND, 0);
break;
case MINUTE:
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
break;
case FIVE_MINUTE:
setData(calendar, 5);
break;
case TEN_MINUTE:
setData(calendar, 10);
break;
case FIFTEEN_MINUTE:
setData(calendar, 15);
break;
case THIRTY_MINUTE:
setData(calendar, 30);
break;
case WEEK:
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek());
break;
case HOUR:
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 0);
break;
case DAY:
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
case MONTH:
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.DAY_OF_MONTH, 1);
break;
case YEAR:
calendar.set(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_YEAR, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
break;
default:
throw new IllegalArgumentException("Invalid time-series function name: " + function);
}
data.setTime(calendar.getTimeInMillis());
return data;
}
/**
* This method sets the calender data based on the interval time of granularity
*/
private void setData(Calendar calendar, int intervalTime) {
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, (calendar.get(Calendar.MINUTE) / intervalTime) * intervalTime);
}
/**
* Below method will be used to initialize the thread local
*/
private void initialize() {
if (calenderThreadLocal.get() == null) {
calenderThreadLocal.set(new GregorianCalendar());
}
if (TIMESERIES_FUNCTION.isEmpty()) {
TIMESERIES_FUNCTION.add("second");
TIMESERIES_FUNCTION.add("minute");
TIMESERIES_FUNCTION.add("five_minute");
TIMESERIES_FUNCTION.add("ten_minute");
TIMESERIES_FUNCTION.add("fifteen_minute");
TIMESERIES_FUNCTION.add("thirty_minute");
TIMESERIES_FUNCTION.add("hour");
TIMESERIES_FUNCTION.add("day");
TIMESERIES_FUNCTION.add("week");
TIMESERIES_FUNCTION.add("month");
TIMESERIES_FUNCTION.add("year");
}
int firstDayOfWeek;
try {
firstDayOfWeek = DaysOfWeekEnum.valueOf(CarbonProperties.getInstance()
.getProperty(CarbonCommonConstants.CARBON_TIMESERIES_FIRST_DAY_OF_WEEK,
CarbonCommonConstants.CARBON_TIMESERIES_FIRST_DAY_OF_WEEK_DEFAULT).toUpperCase())
.getOrdinal();
} catch (IllegalArgumentException ex) {
LOGGER.warn("Invalid value set for first of the week. Considering the default value as: "
+ CarbonCommonConstants.CARBON_TIMESERIES_FIRST_DAY_OF_WEEK_DEFAULT);
firstDayOfWeek =
DaysOfWeekEnum.valueOf(CarbonCommonConstants.CARBON_TIMESERIES_FIRST_DAY_OF_WEEK_DEFAULT)
.getOrdinal();
}
calenderThreadLocal.get().setFirstDayOfWeek(firstDayOfWeek);
}
}