org.datavec.dataframe.columns.packeddata.PackedLocalDate Maven / Gradle / Ivy
Show all versions of datavec-dataframe Show documentation
package org.datavec.dataframe.columns.packeddata;
import com.google.common.base.Strings;
import com.google.common.primitives.Ints;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.time.chrono.IsoChronology;
import java.util.Date;
/**
* A short localdate packed into a single int value. It uses a short for year so the range is about +-30,000 years
*
* The bytes are packed into the int as:
* First two bytes: short (year)
* next byte (month of year)
* last byte (day of month)
*/
public class PackedLocalDate {
/**
* The number of days in a 400 year cycle.
*/
private static final int DAYS_PER_CYCLE = 146097;
/**
* The number of days from year zero to year 1970.
* There are five 400 year cycles from year zero to 2000.
* There are 7 leap years from 1970 to 2000.
*/
static final long DAYS_0000_TO_1970 = (DAYS_PER_CYCLE * 5L) - (30L * 365L + 7L);
public static byte getDayOfMonth(int date) {
return (byte) date; // last byte
}
public static short getYear(int date) {
// get first two bytes, then convert to a short
byte byte1 = (byte) (date >> 24);
byte byte2 = (byte) (date >> 16);
return (short) ((byte2 << 8) + (byte1 & 0xFF));
}
public static LocalDate asLocalDate(int date) {
if (date == Integer.MIN_VALUE) {
return null;
}
// get first two bytes, then each of the other two
byte yearByte1 = (byte) (date >> 24);
byte yearByte2 = (byte) (date >> 16);
return LocalDate.of(
(short) ((yearByte2 << 8) + (yearByte1 & 0xFF)),
(byte) (date >> 8),
(byte) date);
}
public static byte getMonthValue(int date) {
// get the third byte
return (byte) (date >> 8);
}
public static int pack(LocalDate date) {
short year = (short) date.getYear();
byte byte1 = (byte) year;
byte byte2 = (byte) ((year >> 8) & 0xff);
return Ints.fromBytes(
byte1,
byte2,
(byte) date.getMonthValue(),
(byte) date.getDayOfMonth());
}
public static int pack(Date date) {
return pack(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
}
public static int pack(short yr, byte m, byte d) {
byte byte1 = (byte) yr;
byte byte2 = (byte) ((yr >> 8) & 0xff);
return Ints.fromBytes(
byte1,
byte2,
m,
d);
}
public static String toDateString(int date) {
if (date == Integer.MIN_VALUE) {
return "NA";
}
// get first two bytes, then each of the other two
byte yearByte1 = (byte) (date >> 24);
byte yearByte2 = (byte) (date >> 16);
return (short) ((yearByte2 << 8) + (yearByte1 & 0xFF))
+ "-"
+ Strings.padStart(Byte.toString((byte) (date >> 8)), 2, '0')
+ "-"
+ Strings.padStart(Byte.toString((byte) date), 2, '0');
}
public static int getDayOfYear(int packedDate) {
return getMonth(packedDate).firstDayOfYear(isLeapYear(packedDate)) + getDayOfMonth(packedDate) - 1;
}
public static boolean isLeapYear(int packedDate) {
return IsoChronology.INSTANCE.isLeapYear(getYear(packedDate));
}
public static Month getMonth(int packedDate) {
return Month.of(getMonthValue(packedDate));
}
public static int lengthOfMonth(int packedDate) {
switch (getMonthValue(packedDate)) {
case 2:
return (isLeapYear(packedDate) ? 29 : 28);
case 4:
case 6:
case 9:
case 11:
return 30;
default:
return 31;
}
}
public int lengthOfYear(int packedDate) {
return (isLeapYear(packedDate) ? 366 : 365);
}
/**
* Returns the epoch day in a form consistent with the java standard
*/
public static long toEpochDay(int packedDate) {
long y = PackedLocalDate.getYear(packedDate);
long m = PackedLocalDate.getMonthValue(packedDate);
long total = 0;
total += 365 * y;
if (y >= 0) {
total += (y + 3) / 4 - (y + 99) / 100 + (y + 399) / 400;
} else {
total -= y / -4 - y / -100 + y / -400;
}
total += ((367 * m - 362) / 12);
total += getDayOfMonth(packedDate) - 1;
if (m > 2) {
total--;
if (!isLeapYear(packedDate)) {
total--;
}
}
return total - DAYS_0000_TO_1970;
}
public static DayOfWeek getDayOfWeek(int packedDate) {
//TODO(lwhite): This is throwing an exception java.lang.NoSuchMethodError even tho the jdk version seems correct
int dow0 = (int) Math.floorMod(toEpochDay(packedDate) + 3, 7);
return DayOfWeek.of(dow0 + 1);
}
public static int getQuarter(int packedDate) {
Month month = getMonth(packedDate);
switch (month) {
case JANUARY:
case FEBRUARY:
case MARCH:
return 1;
case APRIL:
case MAY:
case JUNE:
return 2;
case JULY:
case AUGUST:
case SEPTEMBER:
return 3;
case OCTOBER:
case NOVEMBER:
case DECEMBER:
return 4;
}
throw new RuntimeException("Failed to extract quarter from packedDate");
}
public static boolean isInQ1(int packedDate) {
return getQuarter(packedDate) == 1;
}
public static boolean isInQ2(int packedDate) {
return getQuarter(packedDate) == 2;
}
public static boolean isInQ3(int packedDate) {
return getQuarter(packedDate) == 3;
}
public static boolean isInQ4(int packedDate) {
return getQuarter(packedDate) == 4;
}
public static boolean isAfter(int packedDate, int value) {
return packedDate > value;
}
public static boolean isBefore(int packedDate, int value) {
return packedDate < value;
}
public static boolean isOnOrBefore(int packedDate, int value) {
return packedDate <= value;
}
public static boolean isOnOrAfter(int packedDate, int value) {
return packedDate >= value;
}
public static boolean isSunday(int packedDate) {
DayOfWeek dayOfWeek = getDayOfWeek(packedDate);
return dayOfWeek == DayOfWeek.SUNDAY;
}
public static boolean isMonday(int packedDate) {
DayOfWeek dayOfWeek = getDayOfWeek(packedDate);
return dayOfWeek == DayOfWeek.MONDAY;
}
public static boolean isTuesday(int packedDate) {
DayOfWeek dayOfWeek = getDayOfWeek(packedDate);
return dayOfWeek == DayOfWeek.TUESDAY;
}
public static boolean isWednesday(int packedDate) {
DayOfWeek dayOfWeek = getDayOfWeek(packedDate);
return dayOfWeek == DayOfWeek.WEDNESDAY;
}
public static boolean isThursday(int packedDate) {
DayOfWeek dayOfWeek = getDayOfWeek(packedDate);
return dayOfWeek == DayOfWeek.THURSDAY;
}
public static boolean isFriday(int packedDate) {
DayOfWeek dayOfWeek = getDayOfWeek(packedDate);
return dayOfWeek == DayOfWeek.FRIDAY;
}
public static boolean isSaturday(int packedDate) {
DayOfWeek dayOfWeek = getDayOfWeek(packedDate);
return dayOfWeek == DayOfWeek.SATURDAY;
}
public static boolean isFirstDayOfMonth(int packedDate) {
return getDayOfMonth(packedDate) == 1;
}
public static boolean isInJanuary(int packedDate) {
return getMonth(packedDate) == Month.JANUARY;
}
public static boolean isInFebruary(int packedDate) {
return getMonth(packedDate) == Month.FEBRUARY;
}
public static boolean isInMarch(int packedDate) {
return getMonth(packedDate) == Month.MARCH;
}
public static boolean isInApril(int packedDate) {
return getMonth(packedDate) == Month.APRIL;
}
public static boolean isInMay(int packedDate) {
return getMonth(packedDate) == Month.MAY;
}
public static boolean isInJune(int packedDate) {
return getMonth(packedDate) == Month.JUNE;
}
public static boolean isInJuly(int packedDate) {
return getMonth(packedDate) == Month.JULY;
}
public static boolean isInAugust(int packedDate) {
return getMonth(packedDate) == Month.AUGUST;
}
public static boolean isInSeptember(int packedDate) {
return getMonth(packedDate) == Month.SEPTEMBER;
}
public static boolean isInOctober(int packedDate) {
return getMonth(packedDate) == Month.OCTOBER;
}
public static boolean isInNovember(int packedDate) {
return getMonth(packedDate) == Month.NOVEMBER;
}
public static boolean isInDecember(int packedDate) {
return getMonth(packedDate) == Month.DECEMBER;
}
public static boolean isLastDayOfMonth(int packedDate) {
return getDayOfMonth(packedDate) == lengthOfMonth(packedDate);
}
public static boolean isInYear(int next, int year) {
return getYear(next) == year;
}
}