Skip to content

Commit

Permalink
METRON-1816 Date format Stellar function (merrimanr) closes apache#1233
Browse files Browse the repository at this point in the history
  • Loading branch information
merrimanr authored and justinleet committed Oct 25, 2018
1 parent cef3532 commit 5fb061c
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
9 changes: 9 additions & 0 deletions metron-stellar/stellar-common/README.md
Expand Up @@ -169,6 +169,7 @@ Where:
| [ `CHOP`](#chop) |
| [ `CHOMP`](#chomp) |
| [ `COUNT_MATCHES`](#count_matches) |
| [ `DATE_FORMAT`](#date_format)
| [ `DAY_OF_MONTH`](#day_of_month) |
| [ `DAY_OF_WEEK`](#day_of_week) |
| [ `DAY_OF_YEAR`](#day_of_year) |
Expand Down Expand Up @@ -379,6 +380,14 @@ Where:
* substring/character - the substring or character to count, may be null.
* Returns: the number of non-overlapping occurrences, 0 if either CharSequence is null.

### `DATE_FORMAT`
* Description: Takes an epoch timestamp and converts it to a date format.
* Input:
* format - DateTime format as a String.
* timestampField - Optional epoch time in Long format. Defaults to now.
* timezone - Optional timezone in String format.
* Returns: Formatted date.

### `DAY_OF_MONTH`
* Description: The numbered day within the month. The first day within the month has a value of 1.
* Input:
Expand Down
Expand Up @@ -28,6 +28,7 @@
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.TimeZone;
Expand Down Expand Up @@ -109,6 +110,13 @@ public static long getEpochTime(String date, String format, Optional<String> tim
return sdf.parse(date).getTime();
}

public static String getDateFormat(String format, Optional<Long> epochTime, Optional<String> timezone) {
Long time = epochTime.orElseGet(System::currentTimeMillis);
TimezonedFormat fmt = timezone.map(s -> new TimezonedFormat(format, s)).orElseGet(() -> new TimezonedFormat(format));
SimpleDateFormat sdf = formatCache.get(fmt).get();
return sdf.format(new Date(time));
}


/**
* Stellar Function: TO_EPOCH_TIMESTAMP
Expand Down Expand Up @@ -144,6 +152,40 @@ public Object apply(List<Object> objects) {
}
}

@Stellar( name="DATE_FORMAT",
description = "Takes an epoch timestamp and converts it to a date format.",
params = {"format - DateTime format as a String."
, "timestampField - Optional epoch time in Long format. Defaults to now."
, "timezone - Optional timezone in String format."},
returns="Formatted date."
)
public static class DateFormat extends BaseStellarFunction {

public Object apply(List<Object> objects) {
int size = objects.size();
Optional<Object> formatObj = Optional.ofNullable(objects.get(0));
Optional<Long> epochObj = Optional.empty();
Optional<String> tzObj = Optional.empty();
if (size > 1) {
if (size == 2) {
if (objects.get(1) == null) {
return null;
}
epochObj = objects.get(1) instanceof Long ? Optional.of((Long) objects.get(1)) : Optional.empty();
tzObj = objects.get(1) instanceof String ? Optional.of((String) objects.get(1)) : Optional.empty();
} else {
epochObj = Optional.ofNullable((Long) objects.get(1));
tzObj = Optional.ofNullable((String) objects.get(2));
}
}
if(formatObj.isPresent()) {
return getDateFormat(formatObj.get().toString(), epochObj, tzObj);
} else {
return null;
}
}
}

/**
* Gets the value from a list of arguments.
*
Expand Down
Expand Up @@ -31,6 +31,7 @@
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
Expand Down Expand Up @@ -225,4 +226,41 @@ public void testDayOfYearNow() {
public void testDayOfYearNull() {
Object result = run("DAY_OF_YEAR(nada)");
}

@Test
public void testDateFormat() {
Object result = run("DATE_FORMAT('EEE MMM dd yyyy hh:mm:ss zzz', epoch, 'EST')");
assertEquals("Thu Aug 25 2016 08:27:10 EST", result);
}

@Test
public void testDateFormatDefault() {
Object result = run("DATE_FORMAT('EEE MMM dd yyyy hh:mm:ss zzzz')");
assertTrue(result.toString().endsWith(TimeZone.getDefault().getDisplayName(true, 1)));
}

@Test
public void testDateFormatNow() {
Object result = run("DATE_FORMAT('EEE MMM dd yyyy hh:mm:ss zzz', 'GMT')");
assertTrue(result.toString().endsWith("GMT"));
}

@Test
public void testDateFormatDefaultTimezone() {
Object result = run("DATE_FORMAT('EEE MMM dd yyyy hh:mm:ss zzzz', epoch)");
assertTrue(result.toString().endsWith(TimeZone.getDefault().getDisplayName(true, 1)));
}

/**
* If refer to variable that does not exist, expect ParseException.
*/
@Test(expected = ParseException.class)
public void testDateFormatNull() {
Object result = run("DATE_FORMAT('EEE MMM dd yyyy hh:mm:ss zzz', nada, 'EST')");
}

@Test(expected = ParseException.class)
public void testDateFormatInvalid() {
Object result = run("DATE_FORMAT('INVALID DATE FORMAT', epoch, 'EST')");
}
}

0 comments on commit 5fb061c

Please sign in to comment.