Add str_to_date function in fe (#1118)
This commit is contained in:
@ -73,6 +73,135 @@ public class FEFunctions {
|
||||
return new StringLiteral(result);
|
||||
}
|
||||
|
||||
@FEFunction(name = "str_to_date", argTypes = { "VARCHAR", "VARCHAR" }, returnType = "DATETIME")
|
||||
public static DateLiteral dateParse(StringLiteral date, StringLiteral fmtLiteral) throws AnalysisException {
|
||||
boolean hasTimePart = false;
|
||||
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
|
||||
|
||||
String formatString = fmtLiteral.getStringValue();
|
||||
boolean escaped = false;
|
||||
for (int i = 0; i < formatString.length(); i++) {
|
||||
char character = formatString.charAt(i);
|
||||
|
||||
if (escaped) {
|
||||
switch (character) {
|
||||
case 'a': // %a Abbreviated weekday name (Sun..Sat)
|
||||
builder.appendDayOfWeekShortText();
|
||||
break;
|
||||
case 'b': // %b Abbreviated month name (Jan..Dec)
|
||||
builder.appendMonthOfYearShortText();
|
||||
break;
|
||||
case 'c': // %c Month, numeric (0..12)
|
||||
builder.appendMonthOfYear(1);
|
||||
break;
|
||||
case 'd': // %d Day of the month, numeric (00..31)
|
||||
builder.appendDayOfMonth(2);
|
||||
break;
|
||||
case 'e': // %e Day of the month, numeric (0..31)
|
||||
builder.appendDayOfMonth(1);
|
||||
break;
|
||||
case 'H': // %H Hour (00..23)
|
||||
builder.appendHourOfDay(2);
|
||||
hasTimePart = true;
|
||||
break;
|
||||
case 'h': // %h Hour (01..12)
|
||||
case 'I': // %I Hour (01..12)
|
||||
builder.appendClockhourOfHalfday(2);
|
||||
hasTimePart = true;
|
||||
break;
|
||||
case 'i': // %i Minutes, numeric (00..59)
|
||||
builder.appendMinuteOfHour(2);
|
||||
hasTimePart = true;
|
||||
break;
|
||||
case 'j': // %j Day of year (001..366)
|
||||
builder.appendDayOfYear(3);
|
||||
break;
|
||||
case 'k': // %k Hour (0..23)
|
||||
builder.appendHourOfDay(1);
|
||||
hasTimePart = true;
|
||||
break;
|
||||
case 'l': // %l Hour (1..12)
|
||||
builder.appendClockhourOfHalfday(1);
|
||||
hasTimePart = true;
|
||||
break;
|
||||
case 'M': // %M Month name (January..December)
|
||||
builder.appendMonthOfYearText();
|
||||
break;
|
||||
case 'm': // %m Month, numeric (00..12)
|
||||
builder.appendMonthOfYear(2);
|
||||
break;
|
||||
case 'p': // %p AM or PM
|
||||
builder.appendHalfdayOfDayText();
|
||||
break;
|
||||
case 'r': // %r Time, 12-hour (hh:mm:ss followed by AM or PM)
|
||||
builder.appendClockhourOfHalfday(2)
|
||||
.appendLiteral(':')
|
||||
.appendMinuteOfHour(2)
|
||||
.appendLiteral(':')
|
||||
.appendSecondOfMinute(2)
|
||||
.appendLiteral(' ')
|
||||
.appendHalfdayOfDayText();
|
||||
hasTimePart = true;
|
||||
break;
|
||||
case 'S': // %S Seconds (00..59)
|
||||
case 's': // %s Seconds (00..59)
|
||||
builder.appendSecondOfMinute(2);
|
||||
hasTimePart = true;
|
||||
break;
|
||||
case 'T': // %T Time, 24-hour (hh:mm:ss)
|
||||
builder.appendHourOfDay(2)
|
||||
.appendLiteral(':')
|
||||
.appendMinuteOfHour(2)
|
||||
.appendLiteral(':')
|
||||
.appendSecondOfMinute(2);
|
||||
hasTimePart = true;
|
||||
break;
|
||||
case 'v': // %v Week (01..53), where Monday is the first day of the week; used with %x
|
||||
builder.appendWeekOfWeekyear(2);
|
||||
break;
|
||||
case 'x': // %x Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v
|
||||
builder.appendWeekyear(4, 4);
|
||||
break;
|
||||
case 'W': // %W Weekday name (Sunday..Saturday)
|
||||
builder.appendDayOfWeekText();
|
||||
break;
|
||||
case 'Y': // %Y Year, numeric, four digits
|
||||
builder.appendYear(4, 4);
|
||||
break;
|
||||
case 'y': // %y Year, numeric (two digits)
|
||||
builder.appendTwoDigitYear(2020);
|
||||
break;
|
||||
case 'f': // %f Microseconds (000000..999999)
|
||||
case 'w': // %w Day of the week (0=Sunday..6=Saturday)
|
||||
case 'U': // %U Week (00..53), where Sunday is the first day of the week
|
||||
case 'u': // %u Week (00..53), where Monday is the first day of the week
|
||||
case 'V': // %V Week (01..53), where Sunday is the first day of the week; used with %X
|
||||
case 'X': // %X Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V
|
||||
case 'D': // %D Day of the month with English suffix (0th, 1st, 2nd, 3rd, …)
|
||||
throw new AnalysisException(String.format("%%%s not supported in date format string", character));
|
||||
case '%': // %% A literal "%" character
|
||||
builder.appendLiteral('%');
|
||||
break;
|
||||
default: // %<x> The literal character represented by <x>
|
||||
builder.appendLiteral(character);
|
||||
break;
|
||||
}
|
||||
escaped = false;
|
||||
} else if (character == '%') {
|
||||
escaped = true;
|
||||
} else {
|
||||
builder.appendLiteral(character);
|
||||
}
|
||||
}
|
||||
|
||||
Date retDate = new Date(builder.toFormatter().parseMillis(date.getStringValue()));
|
||||
if (hasTimePart) {
|
||||
return new DateLiteral(DateFormatUtils.format(retDate, "yyyy-MM-dd HH:mm:ss"), Type.DATETIME);
|
||||
} else {
|
||||
return new DateLiteral(DateFormatUtils.format(retDate, "yyyy-MM-dd"), Type.DATE);
|
||||
}
|
||||
}
|
||||
|
||||
@FEFunction(name = "date_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
|
||||
public static DateLiteral dateSub(LiteralExpr date, LiteralExpr day) throws AnalysisException {
|
||||
Date d = new Date(getTime(date));
|
||||
|
||||
@ -26,6 +26,10 @@ import org.apache.doris.common.AnalysisException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/*
|
||||
* Author: Chenmingyu
|
||||
* Date: Mar 13, 2019
|
||||
@ -87,4 +91,64 @@ public class FEFunctionsTest {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateParseTest() {
|
||||
TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
|
||||
TimeZone.setDefault(tz);
|
||||
try {
|
||||
Assert.assertEquals("2013-05-10", FEFunctions.dateParse(new StringLiteral("2013,05,10"), new StringLiteral("%Y,%m,%d")).getStringValue());
|
||||
Assert.assertEquals("2013-05-17 00:35:10", FEFunctions.dateParse(new StringLiteral("2013-05-17 12:35:10"), new StringLiteral("%Y-%m-%d %h:%i:%s")).getStringValue());
|
||||
Assert.assertEquals("2013-05-17 00:35:10", FEFunctions.dateParse(new StringLiteral("2013-05-17 00:35:10"), new StringLiteral("%Y-%m-%d %H:%i:%s")).getStringValue());
|
||||
Assert.assertEquals("2013-05-17 00:35:10", FEFunctions.dateParse(new StringLiteral("2013-05-17 12:35:10 AM"), new StringLiteral("%Y-%m-%d %h:%i:%s %p")).getStringValue());
|
||||
Assert.assertEquals("2013-05-17 12:35:10", FEFunctions.dateParse(new StringLiteral("2013-05-17 12:35:10 PM"), new StringLiteral("%Y-%m-%d %h:%i:%s %p")).getStringValue());
|
||||
Assert.assertEquals("2013-05-17 23:35:10", FEFunctions.dateParse(new StringLiteral("abc 2013-05-17 fff 23:35:10 xyz"), new StringLiteral("abc %Y-%m-%d fff %H:%i:%s xyz")).getStringValue());
|
||||
Assert.assertEquals("2016-01-28 23:45:46", FEFunctions.dateParse(new StringLiteral("28-JAN-16 11.45.46 PM"), new StringLiteral("%d-%b-%y %l.%i.%s %p")).getStringValue());
|
||||
Assert.assertEquals("2019-05-09", FEFunctions.dateParse(new StringLiteral("2019/May/9"), new StringLiteral("%Y/%b/%d")).getStringValue());
|
||||
Assert.assertEquals("2019-05-09", FEFunctions.dateParse(new StringLiteral("2019,129"), new StringLiteral("%Y,%j")).getStringValue());
|
||||
Assert.assertEquals("2019-05-09", FEFunctions.dateParse(new StringLiteral("2019,19,Thursday"), new StringLiteral("%x,%v,%W")).getStringValue());
|
||||
Assert.assertEquals("2019-05-09 12:10:45", FEFunctions.dateParse(new StringLiteral("12:10:45-20190509"), new StringLiteral("%T-%Y%m%d")).getStringValue());
|
||||
Assert.assertEquals("2019-05-09 09:10:45", FEFunctions.dateParse(new StringLiteral("20190509-9:10:45"), new StringLiteral("%Y%m%d-%k:%i:%S")).getStringValue());
|
||||
} catch (AnalysisException e) {
|
||||
fail("Junit test dateParse fail");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%D"));
|
||||
fail("Junit test dateParse fail");
|
||||
} catch (AnalysisException e) {
|
||||
Assert.assertEquals(e.getMessage(), "%D not supported in date format string");
|
||||
}
|
||||
try {
|
||||
FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%U"));
|
||||
fail("Junit test dateParse fail");
|
||||
} catch (AnalysisException e) {
|
||||
Assert.assertEquals(e.getMessage(), "%U not supported in date format string");
|
||||
}
|
||||
try {
|
||||
FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%u"));
|
||||
fail("Junit test dateParse fail");
|
||||
} catch (AnalysisException e) {
|
||||
Assert.assertEquals(e.getMessage(), "%u not supported in date format string");
|
||||
}
|
||||
try {
|
||||
FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%V"));
|
||||
fail("Junit test dateParse fail");
|
||||
} catch (AnalysisException e) {
|
||||
Assert.assertEquals(e.getMessage(), "%V not supported in date format string");
|
||||
}
|
||||
try {
|
||||
FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%w"));
|
||||
fail("Junit test dateParse fail");
|
||||
} catch (AnalysisException e) {
|
||||
Assert.assertEquals(e.getMessage(), "%w not supported in date format string");
|
||||
}
|
||||
try {
|
||||
FEFunctions.dateParse(new StringLiteral("2013-05-17"), new StringLiteral("%X"));
|
||||
fail("Junit test dateParse fail");
|
||||
} catch (AnalysisException e) {
|
||||
Assert.assertEquals(e.getMessage(), "%X not supported in date format string");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ rm ${DORIS_HOME}/fe/build/ -rf
|
||||
rm ${DORIS_HOME}/fe/output/ -rf
|
||||
|
||||
echo "******************************"
|
||||
echo " Runing PaloBe Unittest "
|
||||
echo " Runing DorisFe Unittest "
|
||||
echo "******************************"
|
||||
|
||||
cd ${DORIS_HOME}/fe/
|
||||
|
||||
Reference in New Issue
Block a user