/**
* Copyright 2015 StreamSets Inc.
*
* Licensed under 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 com.streamsets.pipeline.lib.el;
import com.streamsets.pipeline.api.ElFunction;
import com.streamsets.pipeline.api.ElParam;
import com.streamsets.pipeline.api.el.ELEval;
import com.streamsets.pipeline.api.el.ELVars;
import com.streamsets.pipeline.api.impl.Utils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class TimeNowEL {
private static final Logger LOG = LoggerFactory.getLogger(TimeNowEL.class);
public static final String TIME_CONTEXT_VAR = "time";
public static final String TIME_NOW_CONTEXT_VAR = "time_now";
private TimeNowEL() {}
@ElFunction(prefix = TIME_CONTEXT_VAR, name = "now", description = "Creates a Datetime object set to the current " +
"time.")
public static Date getTimeNowFunc() {
Date now = (Date) ELEval.getVariablesInScope().getContextVariable(TIME_NOW_CONTEXT_VAR);
if(null == now) {
now = new Date();
}
return now;
}
@ElFunction(prefix = TIME_CONTEXT_VAR, name = "trimDate", description = "Set date portion of datetime expression to January 1, 1970")
@SuppressWarnings("deprecation")
public static Date trimDate(@ElParam("datetime") Date in) {
if(in == null) {
return null;
}
Date ret = new Date(in.getTime());
ret.setYear(70);
ret.setMonth(0);
ret.setDate(1);
return ret;
}
@ElFunction(prefix = TIME_CONTEXT_VAR, name = "trimTime", description = "Set time portion of datetime expression to 00:00:00")
@SuppressWarnings("deprecation")
public static Date trimTime(@ElParam("datetime") Date in) {
if(in == null) {
return null;
}
Date ret = new Date(in.getTime());
ret.setHours(0);
ret.setMinutes(0);
ret.setSeconds(0);
return ret;
}
public static void setTimeNowInContext(ELVars variables, Date now) {
Utils.checkNotNull(variables, "variables");
variables.addContextVariable(TIME_NOW_CONTEXT_VAR, now);
}
@ElFunction(prefix = TIME_CONTEXT_VAR,
name = "millisecondsToDateTime",
description = "Convert epoch in milliseconds to DateTime")
public static Date millisecondsToDateTime(@ElParam("long") long in) {
return new Date(in);
}
@ElFunction(prefix = TIME_CONTEXT_VAR,
name = "dateTimeToMilliseconds",
description = "Convert DateTime to epoch in milliseconds")
public static long dateTimeToMilliseconds(@ElParam("datetime") Date in) {
if (in == null) {
return 0;
}
return in.getTime();
}
@ElFunction(prefix = TIME_CONTEXT_VAR,
name = "extractStringFromDate",
description = "Format a date into a string, based on an output format specification")
public static String millisecondsToStringDate(@ElParam("datetime") Date in, @ElParam("string") String outputFormat) {
if(in == null || outputFormat == null || outputFormat.isEmpty()) {
return "";
}
SimpleDateFormat formatter = new SimpleDateFormat(outputFormat);
return formatter.format(in);
}
@ElFunction(prefix = TIME_CONTEXT_VAR,
name = "extractLongFromDate",
description = "Format a date into a long, based on an output format specification")
public static long milliSecondsToLongDate(@ElParam("datetime") Date in, @ElParam("string") String outputFormat)
throws NumberFormatException {
if(in == null || outputFormat == null || outputFormat.isEmpty()) {
return 0;
}
SimpleDateFormat formatter = new SimpleDateFormat(outputFormat);
String str = formatter.format(in);
String value = str.replaceAll("[^0-9]","");
return Long.parseLong(value);
}
@ElFunction(prefix = TIME_CONTEXT_VAR, name = "extractDateFromString", description = "Format a String date into a date.")
public static Date extractDateFromString(
@ElParam("dateTimeString") String dateTimeString,
@ElParam("dateFormat") String dateFormat
) throws ParseException{
if (StringUtils.isEmpty(dateTimeString)) {
LOG.error(Utils.format("Invalid parameter - Date String is null/empty"));
return null;
}
if (StringUtils.isEmpty(dateFormat)) {
LOG.error(Utils.format("Invalid parameter - Date Format is null/empty"));
return null;
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);
return simpleDateFormat.parse(dateTimeString);
}
@ElFunction(prefix = TIME_CONTEXT_VAR, name = "extractStringFromDateTZ", description = "Format a Date into a " +
"string" + " date, adjusting for time zone.")
public static String extractStringFromDateTZ(
@ElParam("datetime") Date in, @ElParam("timezone") String timeZone, @ElParam("dateFormat") String outputFormat
) {
if (in == null) {
LOG.error(Utils.format("Invalid parameter - Date is null"));
return "";
}
if (StringUtils.isEmpty(outputFormat) || StringUtils.isEmpty(timeZone)) {
LOG.error(Utils.format("Invalid parameter - outputFormat or timeZone"));
return "";
}
TimeZone tz = TimeZone.getTimeZone(timeZone);
// TimeZone.getTimeZone() returns "GMT" by default
// when the time zone is not valid.
//
// so we must check if the user asked for "GMT". otherwise,
// if TimeZone.getTimeZone() returned GMT, the input time zone is not valid.
//
if ("GMT".equals(tz.getID()) && (!"GMT".equals(timeZone))) {
LOG.error(Utils.format("Error matching time zone/invalid timezone. '{}' returning empty ", timeZone));
return "";
}
SimpleDateFormat formatter;
try {
formatter = new SimpleDateFormat(outputFormat);
} catch (IllegalArgumentException ex) {
LOG.error(Utils.format("SimpleDateFormatter error. Invalid outputFormat '{}' or timezone '{}'",
outputFormat,
timeZone,
ex
));
return "";
}
formatter.setTimeZone(tz);
return formatter.format(in);
}
@ElFunction(prefix = TIME_CONTEXT_VAR,
name = "createDateFromStringTZ",
description = "Change String Date / append Timezone to a datetime object")
public static Date createDateFromStringTZ(
@ElParam("Date as String") String inDate,
@ElParam("TimeZone") String timeZone,
@ElParam("Date String's Format") String inFormat
) {
if (StringUtils.isEmpty(inFormat) || StringUtils.isEmpty(timeZone) || StringUtils.isEmpty(inDate)) {
return null;
}
TimeZone tz = TimeZone.getTimeZone(timeZone);
if ("GMT".equals(tz.getID()) && (!"GMT".equals(timeZone))) {
LOG.error(Utils.format("Invalid timezone. '{}'", timeZone));
return null;
}
try {
SimpleDateFormat formatter = new SimpleDateFormat(inFormat);
formatter.setTimeZone(tz);
return (formatter.parse(inDate));
} catch (IllegalArgumentException | ParseException ex) {
LOG.error(Utils.format("Date formatting error. Invalid date '{}', timezone '{}' or format '{}'",
inDate,
timeZone,
inFormat,
ex
));
}
return null;
}
}