text:
/*
 * Licensed 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.facebook.presto.operator.scalar;

import com.facebook.presto.Session;
import com.facebook.presto.spi.PrestoException;
import com.facebook.presto.spi.type.DateType;
import com.facebook.presto.spi.type.SqlDate;
import com.facebook.presto.spi.type.SqlTime;
import com.facebook.presto.spi.type.SqlTimeWithTimeZone;
import com.facebook.presto.spi.type.SqlTimestamp;
import com.facebook.presto.spi.type.SqlTimestampWithTimeZone;
import com.facebook.presto.spi.type.TimeType;
import com.facebook.presto.spi.type.TimeZoneKey;
import com.facebook.presto.spi.type.TimestampType;
import com.facebook.presto.spi.type.Type;
import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalTime;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import static com.facebook.presto.spi.type.BigintType.BIGINT;
import static com.facebook.presto.spi.type.DoubleType.DOUBLE;
import static com.facebook.presto.spi.type.TimeWithTimeZoneType.TIME_WITH_TIME_ZONE;
import static com.facebook.presto.spi.type.TimeZoneKey.getTimeZoneKey;
import static com.facebook.presto.spi.type.TimeZoneKey.getTimeZoneKeyForOffset;
import static com.facebook.presto.spi.type.TimestampWithTimeZoneType.TIMESTAMP_WITH_TIME_ZONE;
import static com.facebook.presto.spi.type.VarcharType.VARCHAR;
import static com.facebook.presto.util.DateTimeZoneIndex.getDateTimeZone;
import static java.util.Locale.ENGLISH;
import static org.joda.time.Days.daysBetween;
import static org.joda.time.Hours.hoursBetween;
import static org.joda.time.Minutes.minutesBetween;
import static org.joda.time.Months.monthsBetween;
import static org.joda.time.Seconds.secondsBetween;
import static org.joda.time.Weeks.weeksBetween;
import static org.joda.time.Years.yearsBetween;

public class TestDateTimeFunctions
{
    private static final TimeZoneKey TIME_ZONE_KEY = getTimeZoneKey("Asia/Kathmandu");
    private static final DateTimeZone DATE_TIME_ZONE = getDateTimeZone(TIME_ZONE_KEY);
    private static final TimeZoneKey WEIRD_ZONE_KEY = getTimeZoneKey("+07:09");
    private static final DateTimeZone WEIRD_ZONE = getDateTimeZone(WEIRD_ZONE_KEY);

    private static final DateTime DATE = new DateTime(2001, 8, 22, 0, 0, 0, 0, DateTimeZone.UTC);
    private static final String DATE_LITERAL = "DATE '2001-08-22'";

    private static final DateTime TIME = new DateTime(1970, 1, 1, 3, 4, 5, 321, DATE_TIME_ZONE);
    private static final String TIME_LITERAL = "TIME '03:04:05.321'";
    private static final DateTime WEIRD_TIME = new DateTime(1970, 1, 1, 3, 4, 5, 321, WEIRD_ZONE);
    private static final String WEIRD_TIME_LITERAL = "TIME '03:04:05.321 +07:09'";

    private static final DateTime TIMESTAMP = new DateTime(2001, 8, 22, 3, 4, 5, 321, DATE_TIME_ZONE);
    private static final String TIMESTAMP_LITERAL = "TIMESTAMP '2001-08-22 03:04:05.321'";
    private static final DateTime WEIRD_TIMESTAMP = new DateTime(2001, 8, 22, 3, 4, 5, 321, WEIRD_ZONE);
    private static final String WEIRD_TIMESTAMP_LITERAL = "TIMESTAMP '2001-08-22 03:04:05.321 +07:09'";

    private static final TimeZoneKey WEIRD_TIME_ZONE_KEY = getTimeZoneKeyForOffset(7 * 60 + 9);
    private Session session;
    private FunctionAssertions functionAssertions;

    @BeforeClass
    public void setUp()
    {
        session = Session.builder()
                .setUser("user")
                .setSource("test")
                .setCatalog("catalog")
                .setSchema("schema")
                .setTimeZoneKey(TIME_ZONE_KEY)
                .setLocale(ENGLISH)
                .build();
        functionAssertions = new FunctionAssertions(session);
    }

    @Test
    public void testCurrentDate()
            throws Exception
    {
        // current date is the time at midnight in the session time zone
        DateMidnight dateMidnight = new DateMidnight(session.getStartTime(), DATE_TIME_ZONE);
        int days = (int) TimeUnit.MILLISECONDS.toDays(dateMidnight.getMillis());
        assertFunction("CURRENT_DATE", DateType.DATE, new SqlDate(days));
    }

    @Test
    public void testLocalTime()
            throws Exception
    {
        long millis = new LocalTime(session.getStartTime(), DATE_TIME_ZONE).getMillisOfDay();
        functionAssertions.assertFunction("LOCALTIME", TimeType.TIME, toTime(millis));
    }

    @Test
    public void testCurrentTime()
            throws Exception
    {
        long millis = new LocalTime(session.getStartTime(), DATE_TIME_ZONE).getMillisOfDay();
        functionAssertions.assertFunction("CURRENT_TIME", TIME_WITH_TIME_ZONE, new SqlTimeWithTimeZone(millis, session.getTimeZoneKey()));
    }

    @Test
    public void testLocalTimestamp()
    {
        functionAssertions.assertFunction("localtimestamp", TimestampType.TIMESTAMP, toTimestamp(session.getStartTime()));
    }

    @Test
    public void testCurrentTimestamp()
    {
        functionAssertions.assertFunction("current_timestamp", TIMESTAMP_WITH_TIME_ZONE, new SqlTimestampWithTimeZone(session.getStartTime(), session.getTimeZoneKey()));
        functionAssertions.assertFunction("now()", TIMESTAMP_WITH_TIME_ZONE, new SqlTimestampWithTimeZone(session.getStartTime(), session.getTimeZoneKey()));
    }

    @Test
    public void testFromUnixTime()
    {
        DateTime dateTime = new DateTime(2001, 1, 22, 3, 4, 5, 0, DATE_TIME_ZONE);
        double seconds = dateTime.getMillis() / 1000.0;
        assertFunction("from_unixtime(" + seconds + ")", TimestampType.TIMESTAMP, toTimestamp(dateTime));

        dateTime = new DateTime(2001, 1, 22, 3, 4, 5, 888, DATE_TIME_ZONE);
        seconds = dateTime.getMillis() / 1000.0;
        assertFunction("from_unixtime(" + seconds + ")", TimestampType.TIMESTAMP, toTimestamp(dateTime));
    }

    @Test
    public void testToUnixTime()
    {
        assertFunction("to_unixtime(" + TIMESTAMP_LITERAL + ")", DOUBLE, TIMESTAMP.getMillis() / 1000.0);
        assertFunction("to_unixtime(" + WEIRD_TIMESTAMP_LITERAL + ")", DOUBLE, WEIRD_TIMESTAMP.getMillis() / 1000.0);
    }

    @Test
    public void testTimeZone()
    {
        assertFunction("hour(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getHourOfDay());
        assertFunction("minute(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getMinuteOfHour());
        assertFunction("hour(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getHourOfDay());
        assertFunction("minute(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getMinuteOfHour());
        assertFunction("current_timezone()", VARCHAR, TIME_ZONE_KEY.getId());
    }

    @Test
    public void testAtTimeZone()
    {
        functionAssertions.assertFunction("current_timestamp at time zone interval '07:09' hour to minute",
                TIMESTAMP_WITH_TIME_ZONE,
                new SqlTimestampWithTimeZone(session.getStartTime(), WEIRD_TIME_ZONE_KEY));

        functionAssertions.assertFunction("current_timestamp at time zone 'Asia/Oral'",
                TIMESTAMP_WITH_TIME_ZONE,
                new SqlTimestampWithTimeZone(session.getStartTime(), TimeZone.getTimeZone("Asia/Oral")));
        functionAssertions.assertFunction("now() at time zone 'Asia/Oral'",
                TIMESTAMP_WITH_TIME_ZONE,
                new SqlTimestampWithTimeZone(session.getStartTime(), TimeZone.getTimeZone("Asia/Oral")));
        functionAssertions.assertFunction("current_timestamp at time zone '+07:09'",
                TIMESTAMP_WITH_TIME_ZONE,
                new SqlTimestampWithTimeZone(session.getStartTime(), WEIRD_TIME_ZONE_KEY));
    }

    @Test
    public void testPartFunctions()
    {
        assertFunction("second(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getSecondOfMinute());
        assertFunction("minute(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getMinuteOfHour());
        assertFunction("hour(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getHourOfDay());
        assertFunction("day_of_week(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.dayOfWeek().get());
        assertFunction("dow(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.dayOfWeek().get());
        assertFunction("day(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getDayOfMonth());
        assertFunction("day_of_month(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getDayOfMonth());
        assertFunction("day_of_year(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.dayOfYear().get());
        assertFunction("doy(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.dayOfYear().get());
        assertFunction("week(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.weekOfWeekyear().get());
        assertFunction("week_of_year(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.weekOfWeekyear().get());
        assertFunction("month(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getMonthOfYear());
        assertFunction("quarter(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getMonthOfYear() / 4 + 1);
        assertFunction("year(" + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getYear());
        assertFunction("timezone_hour(" + TIMESTAMP_LITERAL + ")", BIGINT, 5);
        assertFunction("timezone_hour(localtimestamp)", BIGINT, 5);
        assertFunction("timezone_hour(current_timestamp)", BIGINT, 5);

        assertFunction("second(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getSecondOfMinute());
        assertFunction("minute(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getMinuteOfHour());
        assertFunction("hour(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getHourOfDay());
        assertFunction("day_of_week(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.dayOfWeek().get());
        assertFunction("dow(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.dayOfWeek().get());
        assertFunction("day(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getDayOfMonth());
        assertFunction("day_of_month(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getDayOfMonth());
        assertFunction("day_of_year(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.dayOfYear().get());
        assertFunction("doy(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.dayOfYear().get());
        assertFunction("week(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.weekOfWeekyear().get());
        assertFunction("week_of_year(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.weekOfWeekyear().get());
        assertFunction("month(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getMonthOfYear());
        assertFunction("quarter(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getMonthOfYear() / 4 + 1);
        assertFunction("year(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getYear());
        assertFunction("timezone_minute(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, 9);
        assertFunction("timezone_hour(" + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, 7);
    }

    @Test
    public void testYearOfWeek()
    {
        assertFunction("year_of_week(DATE '2001-08-22')", BIGINT, 2001);
        assertFunction("yow(DATE '2001-08-22')", BIGINT, 2001);
        assertFunction("year_of_week(DATE '2005-01-02')", BIGINT, 2004);
        assertFunction("year_of_week(DATE '2008-12-28')", BIGINT, 2008);
        assertFunction("year_of_week(DATE '2008-12-29')", BIGINT, 2009);
        assertFunction("year_of_week(DATE '2009-12-31')", BIGINT, 2009);
        assertFunction("year_of_week(DATE '2010-01-03')", BIGINT, 2009);
        assertFunction("year_of_week(TIMESTAMP '2001-08-22 03:04:05.321 +07:09')", BIGINT, 2001);
        assertFunction("year_of_week(TIMESTAMP '2010-01-03 03:04:05.321')", BIGINT, 2009);
    }

    @Test
    public void testExtractFromTimestamp()
    {
        assertFunction("extract(second FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getSecondOfMinute());
        assertFunction("extract(minute FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getMinuteOfHour());
        assertFunction("extract(hour FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getHourOfDay());
        assertFunction("extract(day_of_week FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getDayOfWeek());
        assertFunction("extract(dow FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getDayOfWeek());
        assertFunction("extract(day FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getDayOfMonth());
        assertFunction("extract(day_of_month FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getDayOfMonth());
        assertFunction("extract(day_of_year FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getDayOfYear());
        assertFunction("extract(year_of_week FROM " + TIMESTAMP_LITERAL + ")", BIGINT, 2001);
        assertFunction("extract(doy FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getDayOfYear());
        assertFunction("extract(week FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getWeekOfWeekyear());
        assertFunction("extract(month FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getMonthOfYear());
        assertFunction("extract(quarter FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getMonthOfYear() / 4 + 1);
        assertFunction("extract(year FROM " + TIMESTAMP_LITERAL + ")", BIGINT, TIMESTAMP.getYear());

        assertFunction("extract(second FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getSecondOfMinute());
        assertFunction("extract(minute FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getMinuteOfHour());
        assertFunction("extract(hour FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getHourOfDay());
        assertFunction("extract(day_of_week FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getDayOfWeek());
        assertFunction("extract(dow FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getDayOfWeek());
        assertFunction("extract(day FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getDayOfMonth());
        assertFunction("extract(day_of_month FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getDayOfMonth());
        assertFunction("extract(day_of_year FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getDayOfYear());
        assertFunction("extract(doy FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getDayOfYear());
        assertFunction("extract(week FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getWeekOfWeekyear());
        assertFunction("extract(month FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getMonthOfYear());
        assertFunction("extract(quarter FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getMonthOfYear() / 4 + 1);
        assertFunction("extract(year FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, WEIRD_TIMESTAMP.getYear());
        assertFunction("extract(timezone_minute FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, 9);
        assertFunction("extract(timezone_hour FROM " + WEIRD_TIMESTAMP_LITERAL + ")", BIGINT, 7);
    }

    @Test
    public void testExtractFromTime()
    {
        assertFunction("extract(second FROM " + TIME_LITERAL + ")", BIGINT, 5);
        assertFunction("extract(minute FROM " + TIME_LITERAL + ")", BIGINT, 4);
        assertFunction("extract(hour FROM " + TIME_LITERAL + ")", BIGINT, 3);

        assertFunction("extract(second FROM " + WEIRD_TIME_LITERAL + ")", BIGINT, 5);
        assertFunction("extract(minute FROM " + WEIRD_TIME_LITERAL + ")", BIGINT, 4);
        assertFunction("extract(hour FROM " + WEIRD_TIME_LITERAL + ")", BIGINT, 3);
    }

    @Test
    public void testExtractFromDate()
    {
        assertFunction("extract(day_of_week FROM " + DATE_LITERAL + ")", BIGINT, 3);
        assertFunction("extract(dow FROM " + DATE_LITERAL + ")", BIGINT, 3);
        assertFunction("extract(day FROM " + DATE_LITERAL + ")", BIGINT, 22);
        assertFunction("extract(day_of_month FROM " + DATE_LITERAL + ")", BIGINT, 22);
        assertFunction("extract(day_of_year FROM " + DATE_LITERAL + ")", BIGINT, 234);
        assertFunction("extract(doy FROM " + DATE_LITERAL + ")", BIGINT, 234);
        assertFunction("extract(year_of_week FROM " + DATE_LITERAL + ")", BIGINT, 2001);
        assertFunction("extract(yow FROM " + DATE_LITERAL + ")", BIGINT, 2001);
        assertFunction("extract(week FROM " + DATE_LITERAL + ")", BIGINT, 34);
        assertFunction("extract(month FROM " + DATE_LITERAL + ")", BIGINT, 8);
        assertFunction("extract(quarter FROM " + DATE_LITERAL + ")", BIGINT, 3);
        assertFunction("extract(year FROM " + DATE_LITERAL + ")", BIGINT, 2001);

        assertFunction("extract(quarter FROM DATE '2001-01-01')", BIGINT, 1);
        assertFunction("extract(quarter FROM DATE '2001-03-31')", BIGINT, 1);
        assertFunction("extract(quarter FROM DATE '2001-04-01')", BIGINT, 2);
        assertFunction("extract(quarter FROM DATE '2001-06-30')", BIGINT, 2);
        assertFunction("extract(quarter FROM DATE '2001-07-01')", BIGINT, 3);
        assertFunction("extract(quarter FROM DATE '2001-09-30')", BIGINT, 3);
        assertFunction("extract(quarter FROM DATE '2001-10-01')", BIGINT, 4);
        assertFunction("extract(quarter FROM DATE '2001-12-31')", BIGINT, 4);

        assertFunction("extract(quarter FROM TIMESTAMP '2001-01-01 00:00:00.000')", BIGINT, 1);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-03-31 23:59:59.999')", BIGINT, 1);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-04-01 00:00:00.000')", BIGINT, 2);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-06-30 23:59:59.999')", BIGINT, 2);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-07-01 00:00:00.000')", BIGINT, 3);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-09-30 23:59:59.999')", BIGINT, 3);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-10-01 00:00:00.000')", BIGINT, 4);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-12-31 23:59:59.999')", BIGINT, 4);

        assertFunction("extract(quarter FROM TIMESTAMP '2001-01-01 00:00:00.000 +06:00')", BIGINT, 1);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-03-31 23:59:59.999 +06:00')", BIGINT, 1);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-04-01 00:00:00.000 +06:00')", BIGINT, 2);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-06-30 23:59:59.999 +06:00')", BIGINT, 2);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-07-01 00:00:00.000 +06:00')", BIGINT, 3);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-09-30 23:59:59.999 +06:00')", BIGINT, 3);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-10-01 00:00:00.000 +06:00')", BIGINT, 4);
        assertFunction("extract(quarter FROM TIMESTAMP '2001-12-31 23:59:59.999 +06:00')", BIGINT, 4);
    }

    @Test
    public void testExtractFromInterval()
    {
        assertFunction("extract(second FROM INTERVAL '5' SECOND)", BIGINT, 5);
        assertFunction("extract(second FROM INTERVAL '65' SECOND)", BIGINT, 5);

        assertFunction("extract(minute FROM INTERVAL '4' MINUTE)", BIGINT, 4);
        assertFunction("extract(minute FROM INTERVAL '64' MINUTE)", BIGINT, 4);
        assertFunction("extract(minute FROM INTERVAL '247' SECOND)", BIGINT, 4);

        assertFunction("extract(hour FROM INTERVAL '3' HOUR)", BIGINT, 3);
        assertFunction("extract(hour FROM INTERVAL '27' HOUR)", BIGINT, 3);
        assertFunction("extract(hour FROM INTERVAL '187' MINUTE)", BIGINT, 3);

        assertFunction("extract(day FROM INTERVAL '2' DAY)", BIGINT, 2);
        assertFunction("extract(day FROM INTERVAL '55' HOUR)", BIGINT, 2);

        assertFunction("extract(month FROM INTERVAL '3' MONTH)", BIGINT, 3);
        assertFunction("extract(month FROM INTERVAL '15' MONTH)", BIGINT, 3);

        assertFunction("extract(year FROM INTERVAL '2' YEAR)", BIGINT, 2);
        assertFunction("extract(year FROM INTERVAL '29' MONTH)", BIGINT, 2);
    }

    @Test
    public void testTruncateTimestamp()
    {
        DateTime result = TIMESTAMP;
        result = result.withMillisOfSecond(0);
        assertFunction("date_trunc('second', " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(result));

        result = result.withSecondOfMinute(0);
        assertFunction("date_trunc('minute', " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(result));

        result = result.withMinuteOfHour(0);
        assertFunction("date_trunc('hour', " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(result));

        result = result.withHourOfDay(0);
        assertFunction("date_trunc('day', " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(result));

        result = result.withDayOfMonth(20);
        assertFunction("date_trunc('week', " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(result));

        result = result.withDayOfMonth(1);
        assertFunction("date_trunc('month', " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(result));

        result = result.withMonthOfYear(7);
        assertFunction("date_trunc('quarter', " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(result));

        result = result.withMonthOfYear(1);
        assertFunction("date_trunc('year', " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(result));

        result = WEIRD_TIMESTAMP;
        result = result.withMillisOfSecond(0);
        assertFunction("date_trunc('second', " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(result));

        result = result.withSecondOfMinute(0);
        assertFunction("date_trunc('minute', " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(result));

        result = result.withMinuteOfHour(0);
        assertFunction("date_trunc('hour', " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(result));

        result = result.withHourOfDay(0);
        assertFunction("date_trunc('day', " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(result));

        result = result.withDayOfMonth(20);
        assertFunction("date_trunc('week', " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(result));

        result = result.withDayOfMonth(1);
        assertFunction("date_trunc('month', " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(result));

        result = result.withMonthOfYear(7);
        assertFunction("date_trunc('quarter', " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(result));

        result = result.withMonthOfYear(1);
        assertFunction("date_trunc('year', " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(result));
    }

    @Test
    public void testTruncateTime()
    {
        DateTime result = TIME;
        result = result.withMillisOfSecond(0);
        assertFunction("date_trunc('second', " + TIME_LITERAL + ")", TimeType.TIME, toTime(result));

        result = result.withSecondOfMinute(0);
        assertFunction("date_trunc('minute', " + TIME_LITERAL + ")", TimeType.TIME, toTime(result));

        result = result.withMinuteOfHour(0);
        assertFunction("date_trunc('hour', " + TIME_LITERAL + ")", TimeType.TIME, toTime(result));

        result = WEIRD_TIME;
        result = result.withMillisOfSecond(0);
        assertFunction("date_trunc('second', " + WEIRD_TIME_LITERAL + ")", TIME_WITH_TIME_ZONE, toTimeWithTimeZone(result));

        result = result.withSecondOfMinute(0);
        assertFunction("date_trunc('minute', " + WEIRD_TIME_LITERAL + ")", TIME_WITH_TIME_ZONE, toTimeWithTimeZone(result));

        result = result.withMinuteOfHour(0);
        assertFunction("date_trunc('hour', " + WEIRD_TIME_LITERAL + ")", TIME_WITH_TIME_ZONE, toTimeWithTimeZone(result));
    }

    @Test
    public void testTruncateDate()
    {
        DateTime result = DATE;
        assertFunction("date_trunc('day', " + DATE_LITERAL + ")", DateType.DATE, toDate(result));

        result = result.withDayOfMonth(20);
        assertFunction("date_trunc('week', " + DATE_LITERAL + ")", DateType.DATE, toDate(result));

        result = result.withDayOfMonth(1);
        assertFunction("date_trunc('month', " + DATE_LITERAL + ")", DateType.DATE, toDate(result));

        result = result.withMonthOfYear(7);
        assertFunction("date_trunc('quarter', " + DATE_LITERAL + ")", DateType.DATE, toDate(result));

        result = result.withMonthOfYear(1);
        assertFunction("date_trunc('year', " + DATE_LITERAL + ")", DateType.DATE, toDate(result));
    }

    @Test
    public void testAddFieldToTimestamp()
    {
        assertFunction("date_add('second', 3, " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(TIMESTAMP.plusSeconds(3)));
        assertFunction("date_add('minute', 3, " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(TIMESTAMP.plusMinutes(3)));
        assertFunction("date_add('hour', 3, " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(TIMESTAMP.plusHours(3)));
        assertFunction("date_add('day', 3, " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(TIMESTAMP.plusDays(3)));
        assertFunction("date_add('week', 3, " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(TIMESTAMP.plusWeeks(3)));
        assertFunction("date_add('month', 3, " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(TIMESTAMP.plusMonths(3)));
        assertFunction("date_add('quarter', 3, " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(TIMESTAMP.plusMonths(3 * 3)));
        assertFunction("date_add('year', 3, " + TIMESTAMP_LITERAL + ")", TimestampType.TIMESTAMP, toTimestamp(TIMESTAMP.plusYears(3)));

        assertFunction("date_add('second', 3, " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(WEIRD_TIMESTAMP.plusSeconds(3)));
        assertFunction("date_add('minute', 3, " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(WEIRD_TIMESTAMP.plusMinutes(3)));
        assertFunction("date_add('hour', 3, " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(WEIRD_TIMESTAMP.plusHours(3)));
        assertFunction("date_add('day', 3, " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(WEIRD_TIMESTAMP.plusDays(3)));
        assertFunction("date_add('week', 3, " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(WEIRD_TIMESTAMP.plusWeeks(3)));
        assertFunction("date_add('month', 3, " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(WEIRD_TIMESTAMP.plusMonths(3)));
        assertFunction("date_add('quarter', 3, " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(WEIRD_TIMESTAMP.plusMonths(3 * 3)));
        assertFunction("date_add('year', 3, " + WEIRD_TIMESTAMP_LITERAL + ")", TIMESTAMP_WITH_TIME_ZONE, toTimestampWithTimeZone(WEIRD_TIMESTAMP.plusYears(3)));
    }

    @Test
    public void testAddFieldToDate()
    {
        assertFunction("date_add('day', 3, " + DATE_LITERAL + ")", DateType.DATE, toDate(DATE.plusDays(3)));
        assertFunction("date_add('week', 3, " + DATE_LITERAL + ")", DateType.DATE, toDate(DATE.plusWeeks(3)));
        assertFunction("date_add('month', 3, " + DATE_LITERAL + ")", DateType.DATE, toDate(DATE.plusMonths(3)));
        assertFunction("date_add('quarter', 3, " + DATE_LITERAL + ")", DateType.DATE, toDate(DATE.plusMonths(3 * 3)));
        assertFunction("date_add('year', 3, " + DATE_LITERAL + ")", DateType.DATE, toDate(DATE.plusYears(3)));
    }

    @Test
    public void testAddFieldToTime()
    {
        assertFunction("date_add('second', 3, " + TIME_LITERAL + ")", TimeType.TIME, toTime(TIME.plusSeconds(3)));
        assertFunction("date_add('minute', 3, " + TIME_LITERAL + ")", TimeType.TIME, toTime(TIME.plusMinutes(3)));
        assertFunction("date_add('hour', 3, " + TIME_LITERAL + ")", TimeType.TIME, toTime(TIME.plusHours(3)));

        assertFunction("date_add('second', 3, " + WEIRD_TIME_LITERAL + ")", TIME_WITH_TIME_ZONE, toTimeWithTimeZone(WEIRD_TIME.plusSeconds(3)));
        assertFunction("date_add('minute', 3, " + WEIRD_TIME_LITERAL + ")", TIME_WITH_TIME_ZONE, toTimeWithTimeZone(WEIRD_TIME.plusMinutes(3)));
        assertFunction("date_add('hour', 3, " + WEIRD_TIME_LITERAL + ")", TIME_WITH_TIME_ZONE, toTimeWithTimeZone(WEIRD_TIME.plusHours(3)));
    }

    @Test
    public void testDateDiffTimestamp()
    {
        DateTime baseDateTime = new DateTime(1960, 5, 3, 7, 2, 9, 678, DATE_TIME_ZONE);
        String baseDateTimeLiteral = "TIMESTAMP '1960-05-03 07:02:09.678'";

        assertFunction("date_diff('second', " + baseDateTimeLiteral + ", " + TIMESTAMP_LITERAL + ")", BIGINT, secondsBetween(baseDateTime, TIMESTAMP).getSeconds());
        assertFunction("date_diff('minute', " + baseDateTimeLiteral + ", " + TIMESTAMP_LITERAL + ")", BIGINT, minutesBetween(baseDateTime, TIMESTAMP).getMinutes());
        assertFunction("date_diff('hour', " + baseDateTimeLiteral + ", " + TIMESTAMP_LITERAL + ")", BIGINT, hoursBetween(baseDateTime, TIMESTAMP).getHours());
        assertFunction("date_diff('day', " + baseDateTimeLiteral + ", " + TIMESTAMP_LITERAL + ")", BIGINT, daysBetween(baseDateTime, TIMESTAMP).getDays());
        assertFunction("date_diff('week', " + baseDateTimeLiteral + ", " + TIMESTAMP_LITERAL + ")", BIGINT, weeksBetween(baseDateTime, TIMESTAMP).getWeeks());
        assertFunction("date_diff('month', " + baseDateTimeLiteral + ", " + TIMESTAMP_LITERAL + ")", BIGINT, monthsBetween(baseDateTime, TIMESTAMP).getMonths());
        assertFunction("date_diff('quarter', " + baseDateTimeLiteral + ", " + TIMESTAMP_LITERAL + ")", BIGINT, monthsBetween(baseDateTime, TIMESTAMP).getMonths() / 3);
        assertFunction("date_diff('year', " + baseDateTimeLiteral + ", " + TIMESTAMP_LITERAL + ")", BIGINT, yearsBetween(baseDateTime, TIMESTAMP).getYears());

        DateTime weirdBaseDateTime = new DateTime(1960, 5, 3, 7, 2, 9, 678, WEIRD_ZONE);
        String weirdBaseDateTimeLiteral = "TIMESTAMP '1960-05-03 07:02:09.678 +07:09'";

        assertFunction("date_diff('second', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIMESTAMP_LITERAL + ")",
                BIGINT,
                secondsBetween(weirdBaseDateTime, WEIRD_TIMESTAMP).getSeconds());
        assertFunction("date_diff('minute', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIMESTAMP_LITERAL + ")",
                BIGINT,
                minutesBetween(weirdBaseDateTime, WEIRD_TIMESTAMP).getMinutes());
        assertFunction("date_diff('hour', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIMESTAMP_LITERAL + ")",
                BIGINT,
                hoursBetween(weirdBaseDateTime, WEIRD_TIMESTAMP).getHours());
        assertFunction("date_diff('day', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIMESTAMP_LITERAL + ")",
                BIGINT,
                daysBetween(weirdBaseDateTime, WEIRD_TIMESTAMP).getDays());
        assertFunction("date_diff('week', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIMESTAMP_LITERAL + ")",
                BIGINT,
                weeksBetween(weirdBaseDateTime, WEIRD_TIMESTAMP).getWeeks());
        assertFunction("date_diff('month', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIMESTAMP_LITERAL + ")",
                BIGINT,
                monthsBetween(weirdBaseDateTime, WEIRD_TIMESTAMP).getMonths());
        assertFunction("date_diff('quarter', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIMESTAMP_LITERAL + ")",
                BIGINT,
                monthsBetween(weirdBaseDateTime, WEIRD_TIMESTAMP).getMonths() / 3);
        assertFunction("date_diff('year', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIMESTAMP_LITERAL + ")",
                BIGINT,
                yearsBetween(weirdBaseDateTime, WEIRD_TIMESTAMP).getYears());
    }

    @Test
    public void testDateDiffDate()
    {
        DateTime baseDateTime = new DateTime(1960, 5, 3, 0, 0, 0, 0, DateTimeZone.UTC);
        String baseDateTimeLiteral = "DATE '1960-05-03'";

        assertFunction("date_diff('day', " + baseDateTimeLiteral + ", " + DATE_LITERAL + ")", BIGINT, daysBetween(baseDateTime, DATE).getDays());
        assertFunction("date_diff('week', " + baseDateTimeLiteral + ", " + DATE_LITERAL + ")", BIGINT, weeksBetween(baseDateTime, DATE).getWeeks());
        assertFunction("date_diff('month', " + baseDateTimeLiteral + ", " + DATE_LITERAL + ")", BIGINT, monthsBetween(baseDateTime, DATE).getMonths());
        assertFunction("date_diff('quarter', " + baseDateTimeLiteral + ", " + DATE_LITERAL + ")", BIGINT, monthsBetween(baseDateTime, DATE).getMonths() / 3);
        assertFunction("date_diff('year', " + baseDateTimeLiteral + ", " + DATE_LITERAL + ")", BIGINT, yearsBetween(baseDateTime, DATE).getYears());
    }

    @Test
    public void testDateDiffTime()
    {
        DateTime baseDateTime = new DateTime(1970, 1, 1, 7, 2, 9, 678, DATE_TIME_ZONE);
        String baseDateTimeLiteral = "TIME '07:02:09.678'";

        assertFunction("date_diff('second', " + baseDateTimeLiteral + ", " + TIME_LITERAL + ")", BIGINT, secondsBetween(baseDateTime, TIME).getSeconds());
        assertFunction("date_diff('minute', " + baseDateTimeLiteral + ", " + TIME_LITERAL + ")", BIGINT, minutesBetween(baseDateTime, TIME).getMinutes());
        assertFunction("date_diff('hour', " + baseDateTimeLiteral + ", " + TIME_LITERAL + ")", BIGINT, hoursBetween(baseDateTime, TIME).getHours());

        DateTime weirdBaseDateTime = new DateTime(1970, 1, 1, 7, 2, 9, 678, WEIRD_ZONE);
        String weirdBaseDateTimeLiteral = "TIME '07:02:09.678 +07:09'";

        assertFunction("date_diff('second', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIME_LITERAL + ")", BIGINT, secondsBetween(weirdBaseDateTime, WEIRD_TIME).getSeconds());
        assertFunction("date_diff('minute', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIME_LITERAL + ")", BIGINT, minutesBetween(weirdBaseDateTime, WEIRD_TIME).getMinutes());
        assertFunction("date_diff('hour', " + weirdBaseDateTimeLiteral + ", " + WEIRD_TIME_LITERAL + ")", BIGINT, hoursBetween(weirdBaseDateTime, WEIRD_TIME).getHours());
    }

    @Test
    public void testParseDatetime()
    {
        assertFunction("parse_datetime('1960/01/22 03:04', 'YYYY/MM/DD HH:mm')",
                TIMESTAMP_WITH_TIME_ZONE,
                toTimestampWithTimeZone(new DateTime(1960, 1, 22, 3, 4, 0, 0, DATE_TIME_ZONE)));
        assertFunction("parse_datetime('1960/01/22 03:04 Asia/Oral', 'YYYY/MM/DD HH:mm ZZZZZ')",
                TIMESTAMP_WITH_TIME_ZONE,
                toTimestampWithTimeZone(new DateTime(1960, 1, 22, 3, 4, 0, 0, DateTimeZone.forID("Asia/Oral"))));
        assertFunction("parse_datetime('1960/01/22 03:04 +0500', 'YYYY/MM/DD HH:mm Z')",
                TIMESTAMP_WITH_TIME_ZONE,
                toTimestampWithTimeZone(new DateTime(1960, 1, 22, 3, 4, 0, 0, DateTimeZone.forOffsetHours(5))));
    }

    @Test(expectedExceptions = PrestoException.class, expectedExceptionsMessageRegExp = "Both printing and parsing not supported")
    public void testInvalidDateParseFormat()
    {
        assertFunction("date_parse('%Y-%M-%d', '')", BIGINT, 0);
    }

    @Test
    public void testFormatDatetime()
    {
        assertFunction("format_datetime(" + TIMESTAMP_LITERAL + ", 'YYYY/MM/dd HH:mm')", VARCHAR, "2001/08/22 03:04");
        assertFunction("format_datetime(" + TIMESTAMP_LITERAL + ", 'YYYY/MM/dd HH:mm ZZZZ')", VARCHAR, "2001/08/22 03:04 Asia/Kathmandu");
        assertFunction("format_datetime(" + WEIRD_TIMESTAMP_LITERAL + ", 'YYYY/MM/dd HH:mm')", VARCHAR, "2001/08/22 03:04");
        assertFunction("format_datetime(" + WEIRD_TIMESTAMP_LITERAL + ", 'YYYY/MM/dd HH:mm ZZZZ')", VARCHAR, "2001/08/22 03:04 +07:09");
    }

    @Test
    public void testDateFormat()
    {
        String dateTimeLiteral = "TIMESTAMP '2001-01-09 13:04:05.321'";

        assertFunction("date_format(" + dateTimeLiteral + ", '%a')", VARCHAR, "Tue");
        assertFunction("date_format(" + dateTimeLiteral + ", '%b')", VARCHAR, "Jan");
        assertFunction("date_format(" + dateTimeLiteral + ", '%c')", VARCHAR, "1");
        assertFunction("date_format(" + dateTimeLiteral + ", '%d')", VARCHAR, "09");
        assertFunction("date_format(" + dateTimeLiteral + ", '%e')", VARCHAR, "9");
        assertFunction("date_format(" + dateTimeLiteral + ", '%f')", VARCHAR, "321000");
        assertFunction("date_format(" + dateTimeLiteral + ", '%H')", VARCHAR, "13");
        assertFunction("date_format(" + dateTimeLiteral + ", '%h')", VARCHAR, "01");
        assertFunction("date_format(" + dateTimeLiteral + ", '%I')", VARCHAR, "01");
        assertFunction("date_format(" + dateTimeLiteral + ", '%i')", VARCHAR, "04");
        assertFunction("date_format(" + dateTimeLiteral + ", '%j')", VARCHAR, "009");
        assertFunction("date_format(" + dateTimeLiteral + ", '%k')", VARCHAR, "13");
        assertFunction("date_format(" + dateTimeLiteral + ", '%l')", VARCHAR, "1");
        assertFunction("date_format(" + dateTimeLiteral + ", '%M')", VARCHAR, "January");
        assertFunction("date_format(" + dateTimeLiteral + ", '%m')", VARCHAR, "01");
        assertFunction("date_format(" + dateTimeLiteral + ", '%p')", VARCHAR, "PM");
        assertFunction("date_format(" + dateTimeLiteral + ", '%r')", VARCHAR, "01:04:05 PM");
        assertFunction("date_format(" + dateTimeLiteral + ", '%S')", VARCHAR, "05");
        assertFunction("date_format(" + dateTimeLiteral + ", '%s')", VARCHAR, "05");
        assertFunction("date_format(" + dateTimeLiteral + ", '%T')", VARCHAR, "13:04:05");
        assertFunction("date_format(" + dateTimeLiteral + ", '%v')", VARCHAR, "02");
        assertFunction("date_format(" + dateTimeLiteral + ", '%W')", VARCHAR, "Tuesday");
        assertFunction("date_format(" + dateTimeLiteral + ", '%w')", VARCHAR, "2");
        assertFunction("date_format(" + dateTimeLiteral + ", '%Y')", VARCHAR, "2001");
        assertFunction("date_format(" + dateTimeLiteral + ", '%y')", VARCHAR, "01");
        assertFunction("date_format(" + dateTimeLiteral + ", '%%')", VARCHAR, "%");
        assertFunction("date_format(" + dateTimeLiteral + ", 'foo')", VARCHAR, "foo");
        assertFunction("date_format(" + dateTimeLiteral + ", '%g')", VARCHAR, "g");
        assertFunction("date_format(" + dateTimeLiteral + ", '%4')", VARCHAR, "4");
        assertFunction("date_format(" + dateTimeLiteral + ", '%x %v')", VARCHAR, "2001 02");

        String wierdDateTimeLiteral = "TIMESTAMP '2001-01-09 13:04:05.321 +07:09'";

        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%a')", VARCHAR, "Tue");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%b')", VARCHAR, "Jan");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%c')", VARCHAR, "1");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%d')", VARCHAR, "09");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%e')", VARCHAR, "9");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%f')", VARCHAR, "321000");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%H')", VARCHAR, "13");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%h')", VARCHAR, "01");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%I')", VARCHAR, "01");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%i')", VARCHAR, "04");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%j')", VARCHAR, "009");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%k')", VARCHAR, "13");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%l')", VARCHAR, "1");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%M')", VARCHAR, "January");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%m')", VARCHAR, "01");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%p')", VARCHAR, "PM");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%r')", VARCHAR, "01:04:05 PM");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%S')", VARCHAR, "05");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%s')", VARCHAR, "05");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%T')", VARCHAR, "13:04:05");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%v')", VARCHAR, "02");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%W')", VARCHAR, "Tuesday");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%w')", VARCHAR, "2");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%Y')", VARCHAR, "2001");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%y')", VARCHAR, "01");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%%')", VARCHAR, "%");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", 'foo')", VARCHAR, "foo");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%g')", VARCHAR, "g");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%4')", VARCHAR, "4");
        assertFunction("date_format(" + wierdDateTimeLiteral + ", '%x %v')", VARCHAR, "2001 02");

        assertFunction("date_format(TIMESTAMP '2001-01-09 13:04:05.32', '%f')", VARCHAR, "320000");
    }

    @Test
    public void testDateParse()
    {
        assertFunction("date_parse('2013', '%Y')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 1, 1, 0, 0, 0, 0, DATE_TIME_ZONE)));
        assertFunction("date_parse('2013-05', '%Y-%m')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 5, 1, 0, 0, 0, 0, DATE_TIME_ZONE)));
        assertFunction("date_parse('2013-05-17', '%Y-%m-%d')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 5, 17, 0, 0, 0, 0, DATE_TIME_ZONE)));
        assertFunction("date_parse('2013-05-17 12:35:10', '%Y-%m-%d %h:%i:%s')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 5, 17, 0, 35, 10, 0, DATE_TIME_ZONE)));
        assertFunction("date_parse('2013-05-17 12:35:10 PM', '%Y-%m-%d %h:%i:%s %p')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 5, 17, 12, 35, 10, 0, DATE_TIME_ZONE)));
        assertFunction("date_parse('2013-05-17 12:35:10 AM', '%Y-%m-%d %h:%i:%s %p')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 5, 17, 0, 35, 10, 0, DATE_TIME_ZONE)));

        assertFunction("date_parse('2013-05-17 00:35:10', '%Y-%m-%d %H:%i:%s')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 5, 17, 0, 35, 10, 0, DATE_TIME_ZONE)));
        assertFunction("date_parse('2013-05-17 23:35:10', '%Y-%m-%d %H:%i:%s')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 5, 17, 23, 35, 10, 0, DATE_TIME_ZONE)));
        assertFunction("date_parse('abc 2013-05-17 fff 23:35:10 xyz', 'abc %Y-%m-%d fff %H:%i:%s xyz')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 5, 17, 23, 35, 10, 0, DATE_TIME_ZONE)));

        assertFunction("date_parse('2013 14', '%Y %y')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2014, 1, 1, 0, 0, 0, 0, DATE_TIME_ZONE)));

        assertFunction("date_parse('1998 53', '%x %v')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(1998, 12, 28, 0, 0, 0, 0, DATE_TIME_ZONE)));

        assertFunction("date_parse('1.1', '%s.%f')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(1970, 1, 1, 0, 0, 1, 100, DATE_TIME_ZONE)));
        assertFunction("date_parse('1.01', '%s.%f')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(1970, 1, 1, 0, 0, 1, 10, DATE_TIME_ZONE)));
        assertFunction("date_parse('1.2006', '%s.%f')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(1970, 1, 1, 0, 0, 1, 200, DATE_TIME_ZONE)));
    }

    @Test
    public void testLocale()
    {
        Locale locale = Locale.JAPANESE;
        Session localeSession = Session.builder()
                .setUser("user")
                .setSource("test")
                .setCatalog("catalog")
                .setSchema("schema")
                .setTimeZoneKey(TIME_ZONE_KEY)
                .setLocale(locale)
                .build();

        FunctionAssertions localeAssertions = new FunctionAssertions(localeSession);

        String dateTimeLiteral = "TIMESTAMP '2001-01-09 13:04:05.321'";

        localeAssertions.assertFunction("date_format(" + dateTimeLiteral + ", '%a')", VARCHAR, "火");
        localeAssertions.assertFunction("date_format(" + dateTimeLiteral + ", '%W')", VARCHAR, "火曜日");
        localeAssertions.assertFunction("date_format(" + dateTimeLiteral + ", '%p')", VARCHAR, "午後");
        localeAssertions.assertFunction("date_format(" + dateTimeLiteral + ", '%r')", VARCHAR, "01:04:05 午後");
        localeAssertions.assertFunction("date_format(" + dateTimeLiteral + ", '%b')", VARCHAR, "1");
        localeAssertions.assertFunction("date_format(" + dateTimeLiteral + ", '%M')", VARCHAR, "1月");

        localeAssertions.assertFunction("format_datetime(" + dateTimeLiteral + ", 'EEE')", VARCHAR, "火");
        localeAssertions.assertFunction("format_datetime(" + dateTimeLiteral + ", 'EEEE')", VARCHAR, "火曜日");
        localeAssertions.assertFunction("format_datetime(" + dateTimeLiteral + ", 'a')", VARCHAR, "午後");
        localeAssertions.assertFunction("format_datetime(" + dateTimeLiteral + ", 'MMM')", VARCHAR, "1");
        localeAssertions.assertFunction("format_datetime(" + dateTimeLiteral + ", 'MMMM')", VARCHAR, "1月");

        localeAssertions.assertFunction("date_parse('2013-05-17 12:35:10 午後', '%Y-%m-%d %h:%i:%s %p')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 5, 17, 12, 35, 10, 0, DATE_TIME_ZONE), localeSession));
        localeAssertions.assertFunction("date_parse('2013-05-17 12:35:10 午前', '%Y-%m-%d %h:%i:%s %p')",
                TimestampType.TIMESTAMP,
                toTimestamp(new DateTime(2013, 5, 17, 0, 35, 10, 0, DATE_TIME_ZONE), localeSession));

        localeAssertions.assertFunction("parse_datetime('2013-05-17 12:35:10 午後', 'yyyy-MM-dd hh:mm:ss a')",
                TIMESTAMP_WITH_TIME_ZONE,
                toTimestampWithTimeZone(new DateTime(2013, 5, 17, 12, 35, 10, 0, DATE_TIME_ZONE)));
        localeAssertions.assertFunction("parse_datetime('2013-05-17 12:35:10 午前', 'yyyy-MM-dd hh:mm:ss aaa')",
                TIMESTAMP_WITH_TIME_ZONE,
                toTimestampWithTimeZone(new DateTime(2013, 5, 17, 0, 35, 10, 0, DATE_TIME_ZONE)));
    }

    private void assertFunction(String projection, Type expectedType, Object expected)
    {
        functionAssertions.assertFunction(projection, expectedType, expected);
    }

    private SqlDate toDate(DateTime dateDate)
    {
        long millis = dateDate.getMillis();
        return new SqlDate((int) TimeUnit.MILLISECONDS.toDays(millis));
    }

    private SqlTime toTime(long milliseconds)
    {
        return new SqlTime(milliseconds, session.getTimeZoneKey());
    }

    private SqlTime toTime(DateTime dateTime)
    {
        return new SqlTime(dateTime.getMillis(), session.getTimeZoneKey());
    }

    private SqlTimeWithTimeZone toTimeWithTimeZone(DateTime dateTime)
    {
        return new SqlTimeWithTimeZone(dateTime.getMillis(), dateTime.getZone().toTimeZone());
    }

    private SqlTimestamp toTimestamp(long milliseconds)
    {
        return new SqlTimestamp(milliseconds, session.getTimeZoneKey());
    }

    private SqlTimestamp toTimestamp(DateTime dateTime)
    {
        return new SqlTimestamp(dateTime.getMillis(), session.getTimeZoneKey());
    }

    private SqlTimestamp toTimestamp(DateTime dateTime, Session session)
    {
        return new SqlTimestamp(dateTime.getMillis(), session.getTimeZoneKey());
    }

    private SqlTimestampWithTimeZone toTimestampWithTimeZone(DateTime dateTime)
    {
        return new SqlTimestampWithTimeZone(dateTime.getMillis(), dateTime.getZone().toTimeZone());
    }
}


text:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace BulkCsvInsert
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Iniciando la carga");
            var startTime = DateTime.Now;
            var csvQueueReader = new CsvQueueReader();
            var count = csvQueueReader.LoadFile(ConfigurationManager.AppSettings["filePath"], true);

            Console.WriteLine($"Se cargaron {count} en {(DateTime.Now - startTime).Milliseconds} milisegundos");

            var csvData = csvQueueReader.Read(100);
            var processor = new MySqlProcessor();
            var errorQueue = new ErrorQueueHandler();
            var index = 0;
            while (csvData != null)
            {
                Console.WriteLine($"Insertando {index}");
                var response = processor.Insert(CsvQueryBuilder.GenerateInsert(csvData));

                if (response == -1)
                {
                    break;
                    errorQueue.AddError(csvData);
                }

                index += csvData.Count();

                Console.WriteLine($"Procesado el {(index*100/count)}% {(response == -1 ? "Error":"Exito!")}");

                csvData = csvQueueReader.Read(100);
            }

            errorQueue.WriteErrorFile();
            processor.Dispose();

            Console.ReadLine();

        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
<!--
  ~ Copyright (c)2022 The Android Open Source Project
  ~
  ~ Licensed 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
  ~
  ~      https://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.
  -->

<resources>
    <string name="app_name">Unscramble</string>
    <string name="instructions">Unscramble the word using all the letters.</string>
    <string name="skip">Skip</string>
    <string name="submit">Submit</string>
    <string name="score">Score: %d</string>
    <string name="word_count">%d of 10 words</string>
    <string name="enter_your_word">Enter your word</string>
    <string name="congratulations">Congratulations!</string>
    <string name="you_scored">"You scored: %d"</string>
    <string name="exit">Exit</string>
    <string name="play_again">Play Again</string>
    <string name="wrong_guess">Wrong Guess!</string>
</resources>


text:
package iso20022

// General information about the corporate action event.
type CorporateActionGeneralInformation7 struct {

	// Reference assigned by the account servicer to unambiguously identify a corporate action event.
	CorporateActionEventIdentification *Max35Text `xml:"CorpActnEvtId"`

	// Official and unique reference assigned by the official central body/entity within each market at the beginning of a corporate action event.
	OfficialCorporateActionEventIdentification *Max35Text `xml:"OffclCorpActnEvtId,omitempty"`

	// Type of corporate action event.
	EventType *CorporateActionEventType3Choice `xml:"EvtTp"`

	// Identification of the security concerned by the corporate action.
	UnderlyingSecurityIdentification *SecurityIdentification11 `xml:"UndrlygSctyId,omitempty"`
}

func (c *CorporateActionGeneralInformation7) SetCorporateActionEventIdentification(value string) {
	c.CorporateActionEventIdentification = (*Max35Text)(&value)
}

func (c *CorporateActionGeneralInformation7) SetOfficialCorporateActionEventIdentification(value string) {
	c.OfficialCorporateActionEventIdentification = (*Max35Text)(&value)
}

func (c *CorporateActionGeneralInformation7) AddEventType() *CorporateActionEventType3Choice {
	c.EventType = new(CorporateActionEventType3Choice)
	return c.EventType
}

func (c *CorporateActionGeneralInformation7) AddUnderlyingSecurityIdentification() *SecurityIdentification11 {
	c.UnderlyingSecurityIdentification = new(SecurityIdentification11)
	return c.UnderlyingSecurityIdentification
}


text:
This is a minimal starter pack for web sites development.
It involves the use of:

* **[Grunt](http://gruntjs.com/)**: a JavaScript task runner;
* **[Bower](https://bower.io/)**: a package manager for client side libraries and frameworks;
* **[Composer](https://getcomposer.org/)**: dependency Manager for PHP;
* **[Sass](http://sass-lang.com/)**: a CSS extension language;
* **[Compass](http://compass-style.org/)**: an open-source CSS Authoring Framework;
* **[Susy](http://susy.oddbird.net/)**: a Sass-based grid framework.

## Requires

To use this starter pack you need to install the following libraries in your local environment. Many of these will have to be installed by the terminal. Make sure you are in your user path (run the "cd" command first to be sure).

### **NodeJS**

Click [here](https://nodejs.org/en/) and follow the install instructions.

### **Bower**

Run the following commands:

```bash
sudo npm install -g bower
```
[Source](https://bower.io/#install-bower)

### **Composer**

Run the following commands:
```bash
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('SHA384', 'composer-setup.php') === 'e115a8dc7871f15d853148a7fbac7da27d6c0030b848d9b3dc09e2a0388afed865e6a3d6b3c0fad45c48e2b5fc1196ae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
```

[Source](https://getcomposer.org/download/)

### **Homebrew** (for MacOS only)

Run the following commands:
```bash
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

[Source](http://brew.sh/)

### **Ruby**

Click [here](https://www.ruby-lang.org/it/downloads/) and follow the install instructions.

### **Sass**

Run the following commands:

```bash
sudo gem install sass
```
[Source](http://sass-lang.com/install)

### **Compass**

Run the following commands:

```bash
sudo gem install compass
```
[Source](http://compass-style.org/install/)

### **Susy**

Run the following commands:

```bash
sudo gem install susy
```
[Source](http://susydocs.oddbird.net/en/latest/install/)

## Installation

### **Grunt**

**First installation**

Open the directory in the terminal. Run the command `npm init` and answer to the questions about the package's informations.
Afterward it, launch the `npm install` command. It will install Grunt and all its modules.

> **Note:** for install a new Grunt module, run `npm install [module-name] --save-dev` and remember to add and configure it in the Gruntfile.js.

> **Tip:** to making sure that your NodeJS modules are up to date, run `npm update`.

**Started project**

Open the directory in the terminal. Run the `npm install` command.

### **Bower**

**First installation**

Open the directory in the terminal. Run the command `bower init` and answer to the questions about the package's informations.
For install a JavaScript or CSS library, run `bower install [library-name] --save`.

**Started project**

Open the directory in the terminal. Run the `bower install` command.

### **Composer**

**First installation**

If you need to install a PHP library make sure it is recorded on [Packagist](https://packagist.org/) and install it with the command `composer require [vendor/package]`

> **Tip:** to making sure that your PHP libraries are up to date, run `composer update`.

**Started project**

Open the directory in the terminal. Run the `composer install` command.

## Author

[Davide Caruso](https://davidecaruso.github.io)

## License

Licensed under [MIT](https://opensource.org/licenses/mit-license.php).


text:
package com.sh1r0.caffe_android_demo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by Even on 2017/3/27.
 */

public class SimpleDividerItemDecoration extends RecyclerView.ItemDecoration {
    private Drawable mDivider;

    public SimpleDividerItemDecoration(Context context) {
        mDivider = ContextCompat.getDrawable(context,R.drawable.line_divider);
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        int left = parent.getPaddingLeft();
        int right = parent.getWidth() - parent.getPaddingRight();

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View child = parent.getChildAt(i);

            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            int top = child.getBottom() + params.bottomMargin;
            int bottom = top + mDivider.getIntrinsicHeight();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }
}


text:
/* global ORIENTATION, mobiwork, GET, THREE, BABYLON */

var application = function () {
    let self = this;

    this.Show = function () {
        let view = new mainview();
         view.Show();
    };
};

$(document).ready(function () {
    var app = new application();
    app.Show();
});


text:
package hatena

import (
	"fmt"
	"net/url"
)

var (
	profileURL = fmt.Sprintf("http://api.b.hatena.ne.jp/%d/my", version)
)

type Profile struct {
	IsOauthMixiCheck    bool   `json:"is_oauth_mixi_check"`
	MixiCheckChecked    string `json:"mixi_check_checked"`
	IgnoresRegex        string `json:"ignores_regex"`
	IsOauthEvernote     bool   `json:"is_oauth_evernote"`
	TwitterChecked      string `json:"twitter_checked"`
	Plususer            bool   `json:"plususer"`
	BookmarkCount       int    `json:"bookmark_count"`
	UserPageVersion     string `json:"user_page_version"`
	DefaultSharedLinkTo string `json:"default_shared_link_to"`
	EvernoteChecked     string `json:"evernote_checked"`
	FacebookChecked     string `json:"facebook_checked"`
	Name                string `json:"name"`
	Private             bool   `json:"private"`
	Rkm                 string `json:"rkm"`
	IsOauthTwitter      bool   `json:"is_oauth_twitter"`
	Login               bool   `json:"login"`
	Rks                 string `json:"rks"`
	IsOauthFacebook     bool   `json:"is_oauth_facebook"`
	IsStaff             bool   `json:"is_staff"`
}

// はてなブックマークの
func (a *Authenticator) GetProfile() (*Profile, error) {

	values := make(url.Values)

	p := &Profile{}
	err := a.apiGet(profileURL, values, p)

	return p, err
}


text:
Component::Component()
{
}

Component::~Component()
{
}

void Component::update(float dt)
{
}

void Component::cleanUp()
{
}

const bool Component::isActive()const
{
	return active;
}

const ComponentType Component::getType()const
{
	return type;
}


text:
Subnetworks
-----------------------------

.. automodule:: google.cloud.compute_v1.services.subnetworks
    :members:
    :inherited-members:

.. automodule:: google.cloud.compute_v1.services.subnetworks.pagers
    :members:
    :inherited-members:


text:
  Sarroux est
       un village
       localisé dans le département de Corrèze en Limousin. Elle comptait 422 habitants en 2008.

Le parc de logements, à Sarroux, était réparti en 2011 en deux appartements et 287 maisons soit
 un marché plutôt équilibré.

La ville propose quelques  équipements sportifs, elle dispose, entre autres, de un terrain de sport.

Si vous pensez emmenager à Sarroux, vous pourrez facilement trouver une maison à acheter.

À proximité de Sarroux sont positionnées géographiquement les communes de
Madic située à 4 km, 231 habitants,
Liginiac située à 2 km, 607 habitants,
Champagnac localisée à 6 km, 1 122 habitants,
Bort-les-Orgues localisée à 5 km, 3 260 habitants,
Saint-Pierre située à 4 km, 161 habitants,
Roche-le-Peyroux localisée à 3 km, 83 habitants,
 entre autres. De plus, Sarroux est située à seulement 17 km de Ussel.


text:
"use strict";
// @flow

/**
 * This class will eventually be smarter and access the StackOverflow
 * API and point to direct answers
 */
class StackOverflowSearcher {
  getUrlForRelevantAnswer(errorMessage: string): string {
    return encodeURI(`http://stackoverflow.com/search?q=${errorMessage}`);
  }
}

module.exports = StackOverflowSearcher;


text:
class OrdersController < ApplicationController
  def show
    @order = Order.find(params[:id])
  end

  def new
    @order = Order.new
  end

  def create
    @order = Order.new(params[:order])
    if @order.save
      flash[:notice] = "Successfully created order."
      redirect_to @order
    else
      render :action => 'new'
    end
  end
end


text:
from django.db import models
from apps.registro.models.Establecimiento import Establecimiento
from apps.registro.models.Anexo import Anexo
from apps.registro.models.ExtensionAulica import ExtensionAulica
from apps.titulos.models.CarreraJurisdiccional import CarreraJurisdiccional
import datetime

"Cada año de CarreraJurisdiccionalCohorte, o sea cada Cohorte Generada"
class Cohorte(models.Model):

    PRIMER_ANIO = 1980
    ULTIMO_ANIO = 2050

    carrera_jurisdiccional = models.ForeignKey(CarreraJurisdiccional, related_name='cohortes')
    anio = models.PositiveIntegerField()
    observaciones = models.CharField(max_length = 255, null = True, blank = True)
    establecimientos = models.ManyToManyField(Establecimiento, through="CohorteEstablecimiento")
    anexos = models.ManyToManyField(Anexo, through="CohorteAnexo")
    extensiones_aulicas = models.ManyToManyField(ExtensionAulica, through="CohorteExtensionAulica")
    revisado_jurisdiccion = models.NullBooleanField(default=False, null=True)

    class Meta:
        app_label = 'titulos'
        ordering = ['anio']
        db_table = 'titulos_cohorte'
        unique_together = ('carrera_jurisdiccional', 'anio')

    def __unicode__(self):
        return str(self.anio)

    "Sobreescribo el init para agregarle propiedades"
    def __init__(self, *args, **kwargs):
        super(Cohorte, self).__init__(*args, **kwargs)
        self.aceptada_por_establecimiento = self.aceptada_por_establecimiento()

    "Algún establecimiento está asociado a la cohorte?"
    def asignada_establecimiento(self):
        return self.establecimientos.exists()

    "Algún establecimiento aceptó la cohorte?"
    def aceptada_por_establecimiento(self):
        from apps.titulos.models.CohorteEstablecimiento import CohorteEstablecimiento
        from apps.titulos.models.EstadoCohorteEstablecimiento import EstadoCohorteEstablecimiento
        return CohorteEstablecimiento.objects.filter(cohorte = self, estado__nombre = EstadoCohorteEstablecimiento.REGISTRADA).exists()

    "Override del método para poder inertar un mensaje de error personalizado"
    "@see http://stackoverflow.com/questions/3993560/django-how-to-override-unique-together-error-message"
    def unique_error_message(self, model_class, unique_check):
        if model_class == type(self) and unique_check == ('carrera_jurisdiccional', 'anio'):
            return 'La carrera ya tiene una cohorte asignada ese año.'
        else:
            return super(Cohorte, self).unique_error_message(model_class, unique_check)

    """
    Asocia/elimina los establecimientos desde el formulario masivo
    XXX: los valores "posts" vienen como strings
    """
    def save_establecimientos(self, establecimientos_procesados_ids, current_establecimientos_ids, establecimientos_seleccionados_ids, estado):
        from apps.titulos.models.CohorteEstablecimiento import CohorteEstablecimiento
        from apps.titulos.models.EstadoCohorteEstablecimiento import EstadoCohorteEstablecimiento

        "Borrar los que se des-chequean"
        for est_id in establecimientos_procesados_ids:
            # Si no está en los ids de la página, borrarlo
            if (str(est_id) not in establecimientos_seleccionados_ids) and (est_id in current_establecimientos_ids):
                ce = CohorteEstablecimiento.objects.get(cohorte=self, establecimiento=est_id)
                if not ce.tiene_seguimiento():
                    ce.delete()

        "Agregar los nuevos"
        for est_id in establecimientos_seleccionados_ids:
            "Si no está entre los actuales"
            if int(est_id) not in current_establecimientos_ids:
                # Lo creo y registro el estado
                registro = CohorteEstablecimiento.objects.create(cohorte=self, establecimiento_id=est_id, estado=estado)
                registro.registrar_estado()
            else:
                registro = CohorteEstablecimiento.objects.get(cohorte=self, establecimiento=est_id)
                old_estado = str(registro.estado)
                if old_estado == EstadoCohorteEstablecimiento.RECHAZADA: # Si estaba rechazada, la pongo asignada de nuevo
                    registro.estado = estado

                registro.save()
                if str(old_estado) != str(estado):
                    registro.registrar_estado()

    """
    Asocia/elimina los anexos desde el formulario masivo
    XXX: los valores "posts" vienen como strings
    """
    def save_anexos(self, anexos_procesados_ids, current_anexos_ids, anexos_seleccionados_ids, estado):

        from apps.titulos.models.CohorteAnexo import CohorteAnexo
        from apps.titulos.models.EstadoCohorteAnexo import EstadoCohorteAnexo

        "Borrar los que se des-chequean"
        for anexo_id in anexos_procesados_ids:
            # Si no está en los ids de la página, borrarlo
            if (str(anexo_id) not in anexos_seleccionados_ids) and (anexo_id in current_anexos_ids):
                ca = CohorteAnexo.objects.get(cohorte=self, anexo=anexo_id)
                if not ca.tiene_seguimiento():
                    ca.delete()

        "Agregar los nuevos"
        for anexo_id in anexos_seleccionados_ids:
            "Si no está entre los actuales"
            if int(anexo_id) not in current_anexos_ids:
                # Lo creo y registro el estado
                registro = CohorteAnexo.objects.create(cohorte=self, anexo_id=anexo_id, estado=estado)
                registro.registrar_estado()
            else:
                registro = CohorteAnexo.objects.get(cohorte=self, anexo=anexo_id)

                old_estado = str(registro.estado)
                if old_estado == EstadoCohorteAnexo.RECHAZADA: # Si estaba rechazada, la pongo asignada de nuevo
                    registro.estado = estado

                registro.save()
                if str(old_estado) != str(estado):
                    registro.registrar_estado()

    """
    Asocia/elimina las extensiones áulicas desde el formulario masivo
    XXX: los valores "posts" vienen como strings
    """
    def save_extensiones_aulicas(self, extensiones_aulicas_procesadas_ids, current_extensiones_aulicas_ids, extensiones_aulicas_seleccionadas_ids, estado):

        from apps.titulos.models.CohorteExtensionAulica import CohorteExtensionAulica
        from apps.titulos.models.EstadoCohorteExtensionAulica import EstadoCohorteExtensionAulica

        "Borrar los que se des-chequean"
        for extension_aulica_id in extensiones_aulicas_procesadas_ids:
            if (str(extension_aulica_id) not in extensiones_aulicas_seleccionadas_ids) and (extension_aulica_id in current_extensiones_aulicas_ids): # Si no está en los ids de la página, borrarlo
                cea = CohorteExtensionAulica.objects.get(cohorte=self, extension_aulica=extension_aulica_id)
                if not cea.tiene_seguimiento():
                    cea.delete()

        "Agregar los nuevos"
        for extension_aulica_id in extensiones_aulicas_seleccionadas_ids:
            "Si no está entre los actuales"
            if int(extension_aulica_id) not in current_extensiones_aulicas_ids:
                # Lo creo y registro el estado
                registro = CohorteExtensionAulica.objects.create(cohorte=self, extension_aulica_id=extension_aulica_id, estado=estado)
                registro.registrar_estado()
            else:
                registro = CohorteExtensionAulica.objects.get(cohorte=self, extension_aulica=extension_aulica_id)

                old_estado = str(registro.estado)
                if old_estado == EstadoCohorteExtensionAulica.RECHAZADA: # Si estaba rechazada, la pongo asignada de nuevo
                    registro.estado = estado

                registro.save()
                if str(old_estado) != str(estado):
                    registro.registrar_estado()

    def rechazada_por_establecimiento(self, establecimiento):
        from apps.titulos.models.CohorteEstablecimiento import CohorteEstablecimiento
        try:
            cohorte_establecimiento = CohorteEstablecimiento.objects.get(cohorte__id=self.id, establecimiento__id=establecimiento.id)
        except CohorteEstablecimiento.DoesNotExist:
            return False
        return cohorte_establecimiento.rechazada()

    def rechazada_por_anexo(self, anexo):
        from apps.titulos.models.CohorteAnexo import CohorteAnexo
        try:
            cohorte_anexo = CohorteAnexo.objects.get(cohorte=self, anexo__id=anexo.id)
        except CohorteAnexo.DoesNotExist:
            return False
        return cohorte_anexo.rechazada()

    def rechazada_por_extension_aulica(self, extension_aulica):
        from apps.titulos.models.CohorteExtensionAulica import CohorteExtensionAulica
        try:
            cohorte_ea = CohorteExtensionAulica.objects.get(cohorte=self, extension_aulica__id=extension_aulica.id)
        except CohorteExtensionAulica.DoesNotExist:
            return False
        return cohorte_ea.rechazada()

    def tiene_seguimiento_establecimiento(self, establecimiento):
        from apps.titulos.models.CohorteEstablecimiento import CohorteEstablecimiento
        from apps.titulos.models.CohorteEstablecimientoSeguimiento import CohorteEstablecimientoSeguimiento
        try:
            ce = CohorteEstablecimiento.objects.get(cohorte=self, establecimiento=establecimiento)
        except CohorteEstablecimiento.DoesNotExist:
            return False
        return CohorteEstablecimientoSeguimiento.objects.filter(cohorte_establecimiento__id = ce.id).count() > 0

    def tiene_seguimiento_anexo(self, anexo):
        from apps.titulos.models.CohorteAnexo import CohorteAnexo
        from apps.titulos.models.CohorteAnexoSeguimiento import CohorteAnexoSeguimiento
        try:
            ca = CohorteAnexo.objects.get(cohorte=self, anexo=anexo)
        except CohorteAnexo.DoesNotExist:
            return False
        return CohorteAnexoSeguimiento.objects.filter(cohorte_anexo__id = ca.id).count() > 0

    def tiene_seguimiento_extension_aulica(self, extension_aulica):
        from apps.titulos.models.CohorteExtensionAulica import CohorteExtensionAulica
        from apps.titulos.models.CohorteExtensionAulicaSeguimiento import CohorteExtensionAulicaSeguimiento
        try:
            cea = CohorteExtensionAulica.objects.get(cohorte=self, extension_aulica=extension_aulica)
        except CohorteExtensionAulica.DoesNotExist:
            return False
        return CohorteExtensionAulicaSeguimiento.objects.filter(cohorte_extension_aulica__id = cea.id).count() > 0


text:
var assert = require('assert'),
    fs = require('fs'),
    sys = require('sys');

exports.testrunner = require('./testrunner');

var assertion = function(obj){
    return {
        method: obj.method || '',
        message: obj.message || (obj.error && obj.error.message) || '',
        error: obj.error,
        passed: function(){return !this.error;},
        failed: function(){return Boolean(this.error);}
    };
};

var assertions = function(arr, duration){
    var that = arr || [];
    that.__defineGetter__('failures', function(){
        return this.reduce(function(a,x){
            return x.failed() ? a+1 : a;
        }, 0);
    });
    that.duration = duration || 0;
    return that;
};

var testEnv = function(start, options){
    var expecting;
    var a_list = [];
    options.log = options.log || function(){}; // log callback optional

    var wrapAssert = function(new_method, assert_method){
        return function(){
            try {
                assert[assert_method].apply(global, arguments);
                var message = arguments[arguments.length-1];
                var a = assertion({method:new_method, message:message});
            }
            catch (e){
                // deepEqual error message is a bit sucky, lets improve it!
                // e.actual and e.expected could be null or undefined, so
                // using getOwnPropertyDescriptor to see if they exist:
                if(Object.getOwnPropertyDescriptor(e,'actual')
                && Object.getOwnPropertyDescriptor(e,'expected')){

                    var actual = sys.inspect(e.actual).replace(/\n$/,'');
                    var expected = sys.inspect(e.expected).replace(/\n$/,'');
                    var multiline = (
                        actual.indexOf('\n') != -1 ||
                        expected.indexOf('\n') != -1
                    );
                    var spacing = (multiline ? '\n' : ' ');
                    e._message = e.message;
                    e.stack = (
                        e.name + ':' + spacing +
                        actual + spacing + e.operator + spacing +
                        expected + '\n' +
                        e.stack.split('\n').slice(1).join('\n')
                    );
                }
                var a = assertion({method:new_method, error:e});
            }
            a_list.push(a);
            process.nextTick(function(){options.log(a)});
        };
    };

    return {
        done: function(){
            if(expecting !== undefined && expecting != a_list.length){
                var err = new Error(
                    'Expected ' + expecting + ' assertions, ' +
                    a_list.length + ' ran'
                );
                var a = assertion({method:'expect', error:err});
                a_list.push(a);
                process.nextTick(function(){options.log(a);});
            }
            var end = new Date().getTime();
            process.nextTick(function(){
                options.testDone(options.name, assertions(a_list, end-start));
            });
        },
        ok: wrapAssert('ok', 'ok'),
        same: wrapAssert('same', 'deepEqual'),
        equals: wrapAssert('equals', 'equal'),
        expect: function(num){
            expecting = num;
        }
    };
};

exports.runTest = function(fn, options){
    options.log = options.log || function(){}; // log callback optional
    var start = new Date().getTime();
    try {
        fn(testEnv(start, options));
    }
    catch (e){
        var end = new Date().getTime();
        var a = assertion({error:e});
        process.nextTick(function(){
            options.log(a);
            options.testDone(options.name, assertions([a], end-start));
        });
    }
};

exports.runModule = function(mod, options){
    var m_assertions = [];
    var start = new Date().getTime();
    var i = 0;
    var tests = Object.keys(mod);
    if(tests.length){
        var _fn = function(testname){
            (options.testStart || function(){})(testname);
            exports.runTest(mod[testname], {
                name: testname,
                log: options.log,
                testDone: function(name, a_list){
                    m_assertions = m_assertions.concat(a_list);
                    (options.testDone || function(){})(name, a_list);

                    i++;
                    if(i < tests.length){
                        _fn(tests[i]);
                    }
                    else {
                        var end = new Date().getTime();
                        (options.moduleDone || function(){})(
                            options.name, assertions(m_assertions, end-start)
                        );
                    }
                }
            });
        };
        _fn(tests[0] || {});
    }
    else {
        var end = new Date().getTime();
        (options.moduleDone || function(){})(
            options.name, assertions([], end-start)
        );
    }
};

exports.runFiles = function(paths, options){
    var all_assertions = [];
    var start = new Date().getTime();

    if(!paths.length){
        return options.done(assertions(all_assertions));
    }

    var files = paths.reduce(function(a,p){
        var stats = fs.statSync(p);
        if(stats.isFile()){
            return a.concat([p]);
        }
        else if(stats.isDirectory()){
            return a.concat(fs.readdirSync(p).filter(function(filename){
                return /\.js$/.exec(filename);
            }).map(function(filename){
                return [p, filename].join('/');
            }));
        }
    }, []);

    if(!files.length){
        var end = new Date().getTime();
        (options.done || function(){})(assertions([], end-start));
        return;
    }

    var i = 0;
    var _fn = (function(file){
        options.moduleStart(file);
        exports.runModule(require(file.replace(/\.js$/, '')), {
            name: file,
            log: options.log,
            moduleStart: options.moduleStart,
            testStart: options.testStart,
            testDone: options.testDone,
            moduleDone: function(name, a_list){
                all_assertions = all_assertions.concat(a_list);
                (options.moduleDone || function(){}).apply(global, arguments);
                i++;
                if(i < files.length){
                    _fn(files[i]);
                }
                else {
                    var end = new Date().getTime();
                    options.done(assertions(all_assertions, end-start));
                }
            }
        });
    });
    _fn(files[0]);
};


text:
FROM tianon/mariadb

MAINTAINER Tyler Treat <tyler.treat@webfilings.com>

RUN apt-get update

# Install utilities
RUN apt-get install -y git

# Install Python tools
RUN apt-get install -y python python-dev python-distribute python-pip
RUN pip install --upgrade setuptools