[SPARK-8938][SQL] Implement toString for Interval data type

Author: Wenchen Fan <cloud0fan@outlook.com>

Closes #7315 from cloud-fan/toString and squashes the following commits:

4fc8d80 [Wenchen Fan] Implement toString for Interval data type
This commit is contained in:
Wenchen Fan 2015-07-09 10:04:42 -07:00 committed by Reynold Xin
parent a870a82fb6
commit f6c0bd5c37
3 changed files with 119 additions and 6 deletions

View file

@ -353,22 +353,34 @@ class SqlParser extends AbstractSparkSQLParser with DataTypeParser {
integral <~ intervalUnit("microsecond") ^^ { case num => num.toLong }
protected lazy val millisecond: Parser[Long] =
integral <~ intervalUnit("millisecond") ^^ { case num => num.toLong * 1000 }
integral <~ intervalUnit("millisecond") ^^ {
case num => num.toLong * Interval.MICROS_PER_MILLI
}
protected lazy val second: Parser[Long] =
integral <~ intervalUnit("second") ^^ { case num => num.toLong * 1000 * 1000 }
integral <~ intervalUnit("second") ^^ {
case num => num.toLong * Interval.MICROS_PER_SECOND
}
protected lazy val minute: Parser[Long] =
integral <~ intervalUnit("minute") ^^ { case num => num.toLong * 1000 * 1000 * 60 }
integral <~ intervalUnit("minute") ^^ {
case num => num.toLong * Interval.MICROS_PER_MINUTE
}
protected lazy val hour: Parser[Long] =
integral <~ intervalUnit("hour") ^^ { case num => num.toLong * 1000 * 1000 * 3600 }
integral <~ intervalUnit("hour") ^^ {
case num => num.toLong * Interval.MICROS_PER_HOUR
}
protected lazy val day: Parser[Long] =
integral <~ intervalUnit("day") ^^ { case num => num.toLong * 1000 * 1000 * 3600 * 24 }
integral <~ intervalUnit("day") ^^ {
case num => num.toLong * Interval.MICROS_PER_DAY
}
protected lazy val week: Parser[Long] =
integral <~ intervalUnit("week") ^^ { case num => num.toLong * 1000 * 1000 * 3600 * 24 * 7 }
integral <~ intervalUnit("week") ^^ {
case num => num.toLong * Interval.MICROS_PER_WEEK
}
protected lazy val intervalLiteral: Parser[Literal] =
INTERVAL ~> year.? ~ month.? ~ week.? ~ day.? ~ hour.? ~ minute.? ~ second.? ~

View file

@ -23,6 +23,13 @@ import java.io.Serializable;
* The internal representation of interval type.
*/
public final class Interval implements Serializable {
public static final long MICROS_PER_MILLI = 1000L;
public static final long MICROS_PER_SECOND = MICROS_PER_MILLI * 1000;
public static final long MICROS_PER_MINUTE = MICROS_PER_SECOND * 60;
public static final long MICROS_PER_HOUR = MICROS_PER_MINUTE * 60;
public static final long MICROS_PER_DAY = MICROS_PER_HOUR * 24;
public static final long MICROS_PER_WEEK = MICROS_PER_DAY * 7;
public final int months;
public final long microseconds;
@ -44,4 +51,39 @@ public final class Interval implements Serializable {
public int hashCode() {
return 31 * months + (int) microseconds;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("interval");
if (months != 0) {
appendUnit(sb, months / 12, "year");
appendUnit(sb, months % 12, "month");
}
if (microseconds != 0) {
long rest = microseconds;
appendUnit(sb, rest / MICROS_PER_WEEK, "week");
rest %= MICROS_PER_WEEK;
appendUnit(sb, rest / MICROS_PER_DAY, "day");
rest %= MICROS_PER_DAY;
appendUnit(sb, rest / MICROS_PER_HOUR, "hour");
rest %= MICROS_PER_HOUR;
appendUnit(sb, rest / MICROS_PER_MINUTE, "minute");
rest %= MICROS_PER_MINUTE;
appendUnit(sb, rest / MICROS_PER_SECOND, "second");
rest %= MICROS_PER_SECOND;
appendUnit(sb, rest / MICROS_PER_MILLI, "millisecond");
rest %= MICROS_PER_MILLI;
appendUnit(sb, rest, "microsecond");
}
return sb.toString();
}
private void appendUnit(StringBuilder sb, long value, String unit) {
if (value != 0) {
sb.append(" " + value + " " + unit + "s");
}
}
}

View file

@ -0,0 +1,59 @@
/*
* 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.spark.unsafe.types;
import org.junit.Test;
import static junit.framework.Assert.*;
import static org.apache.spark.unsafe.types.Interval.*;
public class IntervalSuite {
@Test
public void equalsTest() {
Interval i1 = new Interval(3, 123);
Interval i2 = new Interval(3, 321);
Interval i3 = new Interval(1, 123);
Interval i4 = new Interval(3, 123);
assertNotSame(i1, i2);
assertNotSame(i1, i3);
assertNotSame(i2, i3);
assertEquals(i1, i4);
}
@Test
public void toStringTest() {
Interval i;
i = new Interval(34, 0);
assertEquals(i.toString(), "interval 2 years 10 months");
i = new Interval(-34, 0);
assertEquals(i.toString(), "interval -2 years -10 months");
i = new Interval(0, 3 * MICROS_PER_WEEK + 13 * MICROS_PER_HOUR + 123);
assertEquals(i.toString(), "interval 3 weeks 13 hours 123 microseconds");
i = new Interval(0, -3 * MICROS_PER_WEEK - 13 * MICROS_PER_HOUR - 123);
assertEquals(i.toString(), "interval -3 weeks -13 hours -123 microseconds");
i = new Interval(34, 3 * MICROS_PER_WEEK + 13 * MICROS_PER_HOUR + 123);
assertEquals(i.toString(), "interval 2 years 10 months 3 weeks 13 hours 123 microseconds");
}
}