All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.thesett.aima.attribute.time.TimeUtils Maven / Gradle / Ivy

Go to download

Library of code developed from 'Artificial Intelligence a Modern Approach', Prentice Hall.

There is a newer version: 0.8.3
Show newest version
/*
 * Copyright The Sett Ltd, 2005 to 2014.
 *
 * 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.thesett.aima.attribute.time;

import java.nio.ByteBuffer;

/**
 * TimeUtils provides static methods for performing time related calculations, particularly conversions between unix
 * timestamps and dates and times.
 *
 * 

*
CRC Card
Responsibilities Collaborations *
Perform conversions to and from times and dates in milliseconds and ASCII formats. *
Write times and dates to byte buffers. *
* * @author Rupert Smith */ public class TimeUtils { /** The number of milliseconds in a second. */ private static final int MILLIS_PER_SECOND = 1000; /** The number of milliseconds in a minute. */ public static final int MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND; /** The number of milliseconds in an hour. */ public static final int MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE; /** The number of milliseconds in a day. */ private static final int MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR; /** The number of milliseconds in a year. */ public static final long MILLIS_PER_YEAR = 365L * MILLIS_PER_DAY; /** The number of milliseconds in a leap year. */ public static final long MILLIS_PER_LEAP_YEAR = 366L * MILLIS_PER_DAY; /** The number of ticks in a minute. */ public static final long TICKS_PER_MINUTE = MILLIS_PER_MINUTE; /** The number of milliseconds in 365.2425 days. */ private static final long MILLIS_PER_REAL_YEAR = (long) (365.2425 * MILLIS_PER_DAY); /** The number of days from 0000 to 1970. */ private static final int DAYS_TO_1970 = 719527; /** Tables the number of days in the year prior to the start of each month, for leap years. */ private static final int[] LEAP_DAYS_IN_YEAR_PRIOR_TO_MONTH = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; /** Tables the number of days in the year prior to the start of each month. */ private static final int[] USUAL_DAYS_IN_YEAR_PRIOR_TO_MONTH = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; /** Tables the number of days in each month, for leap years. */ private static final int[] LEAP_DAYS_IN_MONTH = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /** Tables the number of days in each month, for non leap years. */ private static final int[] USUAL_DAYS_IN_MONTH = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /** The number of milliseconds per day divided by 1024. */ private static final long MILLIS_PER_DAY_OVER_1024 = MILLIS_PER_DAY >> 10; /** The length of a date only in YYYYMMDD format. */ public static final int DATE_ONLY_LENGTH = 8; /** The length of a timestamp in YYYYMMDD-HH:MM:SS format. */ public static final int DATE_TIME_WITHOUT_MILLISECONDS_LENGTH = 17; /** The length of a timestamp in YYYYMMDD-HH:MM:SS.sss format. */ public static final int DATE_TIME_WITH_MILLISECONDS_LENGTH = 21; /** The length of a time of day in HH:MM:SS format. */ public static final int TIME_ONLY_LENGTH_WIHTOUT_MILLISECONDS = 8; /** The length of a time of day in HH:MM:SS.sss format. */ public static final int TIME_ONLY_LENGTH_WITH_MILLISECONDS = 12; /** The length of a time zone offset in [+/-]HH format. */ public static final int TIME_ZONE_WITHOUT_MINUTES_LENGTH = 3; /** The length of a time zone offset in [+/-]HH:MM format. */ public static final int TIME_ZONE_WITH_MINUTES_LENGTH = 6; /** * Converts a field by field timestamp into millisecond ticks. * * @param year The year. * @param month The month. * @param day The day. * @param hours The hours. * @param minutes The minutes. * @param seconds The seconds. * @param milliseconds The milliseconds. * * @return Millisecond ticks since midnight 01/01/1970. */ public static long timestampToTicks(int year, int month, int day, int hours, int minutes, int seconds, int milliseconds) { boolean isLeapYear = isLeapYear(year); long dayComponent = (long) (day - 1) * MILLIS_PER_DAY; long monthComponent = millisToStartOfMonth(month, isLeapYear); long yearComponent = millisToYearStart(year); long hoursComponent = (long) hours * MILLIS_PER_HOUR; long minutesComponent = (long) minutes * MILLIS_PER_MINUTE; long secondsComponent = (long) seconds * MILLIS_PER_SECOND; return dayComponent + monthComponent + yearComponent + hoursComponent + minutesComponent + secondsComponent + milliseconds; } /** * Converts a field by field timestamp into millisecond ticks. * * @param year The year. * @param month The month. * @param day The day. * @param hours The hours. * @param minutes The minutes. * @param seconds The seconds. * * @return Millisecond ticks since midnight 01/01/1970. */ public static long timestampToTicks(int year, int month, int day, int hours, int minutes, int seconds) { boolean isLeapYear = isLeapYear(year); long dayComponent = (long) (day - 1) * MILLIS_PER_DAY; long monthComponent = millisToStartOfMonth(month, isLeapYear); long yearComponent = millisToYearStart(year); long hoursComponent = (long) hours * MILLIS_PER_HOUR; long minutesComponent = (long) minutes * MILLIS_PER_MINUTE; long secondsComponent = (long) seconds * MILLIS_PER_SECOND; return dayComponent + monthComponent + yearComponent + hoursComponent + minutesComponent + secondsComponent; } /** * Converts a field by field timestamp into millisecond ticks. * * @param year The year. * @param month The month. * @param day The day. * * @return Millisecond ticks since midnight 01/01/1970. */ public static long timestampToTicks(int year, int month, int day) { boolean isLeapYear = isLeapYear(year); long dayComponent = (long) (day - 1) * MILLIS_PER_DAY; long monthComponent = millisToStartOfMonth(month, isLeapYear); long yearComponent = millisToYearStart(year); return dayComponent + monthComponent + yearComponent; } /** * Converts a field by field time of day into millisecond ticks. * * @param hour The hours since midnight. * @param minute The minutes. * @param second The seconds. * @param millisecond The milliseconds. * * @return Millisecond ticks since midnight. */ public static long timeOfDayToTicks(int hour, int minute, int second, int millisecond) { return millisecond + (MILLIS_PER_SECOND * second) + (MILLIS_PER_MINUTE * minute) + (MILLIS_PER_HOUR * hour); } /** * Converts a field by field time of day into millisecond ticks. * * @param hour The hours since midnight. * @param minute The minutes. * * @return Millisecond ticks since midnight. */ public static long timeOfDayToTicks(int hour, int minute) { return (MILLIS_PER_MINUTE * minute) + (MILLIS_PER_HOUR * hour); } /** * Extracts the years component of a time in millisecond ticks. * * @param ticks The time in ticks. * * @return The years component of the time. */ public static int ticksToYears(long ticks) { // The number of years is ticks floor divided by number of milliseconds in 365 1/4 days. //return flooredDiv(ticks, MILLIS_PER_REAL_YEAR) + 1970; //return flooredDiv(ticks + ((long)DAYS_TO_1970 * MILLIS_PER_DAY), MILLIS_PER_REAL_YEAR); long unitMillis = MILLIS_PER_YEAR / 2; long i2 = (ticks >> 1) + ((1970L * MILLIS_PER_YEAR) / 2); if (i2 < 0) { i2 = i2 - unitMillis + 1; } int year = (int) (i2 / unitMillis); long yearStart = millisToYearStart(year); long diff = ticks - yearStart; if (diff < 0) { year--; } else if (diff >= (MILLIS_PER_DAY * 365L)) { // One year may need to be added to fix estimate. long oneYear; if (isLeapYear(year)) { oneYear = MILLIS_PER_DAY * 366L; } else { oneYear = MILLIS_PER_DAY * 365L; } yearStart += oneYear; if (yearStart <= ticks) { year++; } } return year; } /** * Extracts the months component of a time in millisecond ticks. * * @param ticks The time in ticks. * * @return The months component of the time. */ public static int ticksToMonths(long ticks) { return getMonthOfYear(ticks, ticksToYears(ticks)); } /** * Extracts the date (day in month) component of a time in millisecond ticks. * * @param ticks The time in ticks. * * @return The date (day in month) component of the time. */ public static int ticksToDate(long ticks) { int year = ticksToYears(ticks); int month = ticksToMonths(ticks); long dayOffset = ticks; dayOffset -= millisToYearStart(year); dayOffset -= isLeapYear(year) ? ((long) LEAP_DAYS_IN_YEAR_PRIOR_TO_MONTH[month - 1] * MILLIS_PER_DAY) : ((long) USUAL_DAYS_IN_YEAR_PRIOR_TO_MONTH[month - 1] * MILLIS_PER_DAY); return (int) (dayOffset / MILLIS_PER_DAY) + 1; } /** * Extracts the hours component of a time in millisecond ticks. * * @param ticks The time in ticks. * * @return The hours component of the time. */ public static int ticksToHours(long ticks) { return (int) (ticks % MILLIS_PER_DAY) / MILLIS_PER_HOUR; } /** * Extracts the minutes component of a time in millisecond ticks. * * @param ticks The time in ticks. * * @return The minutes component of the time. */ public static int ticksToMinutes(long ticks) { return (int) (ticks % MILLIS_PER_HOUR) / MILLIS_PER_MINUTE; } /** * Extracts the seconds component of a time in millisecond ticks. * * @param ticks The time in ticks. * * @return The seconds component of the time. */ public static int ticksToSeconds(long ticks) { return (int) (ticks % MILLIS_PER_MINUTE) / MILLIS_PER_SECOND; } /** * Extracts the milliseconds component of a time in millisecond ticks. * * @param ticks The time in ticks. * * @return The milliseconds component of the time. */ public static int ticksToMilliseconds(long ticks) { return (int) (ticks % MILLIS_PER_SECOND); } /** * Sets the component of the timestamp, returning the new timestamp with updated component. * * @param ticks The time in ticks. * @param hours The new hours field. * * @return The new time in ticks. */ public static long ticksWithHoursSetTo(long ticks, int hours) { long oldHours = ticksToHours(ticks); return ticks - (oldHours * MILLIS_PER_HOUR) + (hours * MILLIS_PER_HOUR); } /** * Sets the minutes component of the timestamp, returning the new timestamp with updated component. * * @param ticks The time in ticks. * @param minutes The new minutes field. * * @return The new time in ticks. */ public static long ticksWithMinutesSetTo(long ticks, int minutes) { long oldMinutes = ticksToMinutes(ticks); return ticks - (oldMinutes * MILLIS_PER_MINUTE) + (minutes * MILLIS_PER_MINUTE); } /** * Sets the seconds component of the timestamp, returning the new timestamp with updated component. * * @param ticks The time in ticks. * @param seconds The new seconds field. * * @return The new time in ticks. */ public static long ticksWithSecondsSetTo(long ticks, int seconds) { long oldSeconds = ticksToSeconds(ticks); return ticks - (oldSeconds * MILLIS_PER_SECOND) + (seconds * MILLIS_PER_SECOND); } /** * Sets the milliseconds component of the timestamp, returning the new timestamp with updated component. * * @param ticks The time in ticks. * @param milliseconds The new milliseconds field. * * @return The new time in ticks. */ public static long ticksWithMillisecondsSetTo(long ticks, int milliseconds) { long oldMillis = ticksToMilliseconds(ticks); return ticks - oldMillis + milliseconds; } /** * Sets the year component of the timestamp, returning the new timestamp with updated component. * * @param ticks The time in ticks. * @param year The new year field. * * @return The new time in ticks. */ public static long ticksWithYearSetTo(long ticks, int year) { int oldYear = ticksToYears(ticks); return ticks - millisToYearStart(oldYear) + millisToYearStart(year); } /** * Sets the month component of the timestamp, returning the new timestamp with updated component. * * @param ticks The time in ticks. * @param month The new month field. * * @return The new time in ticks. */ public static long ticksWithMonthSetTo(long ticks, int month) { int year = ticksToYears(ticks); boolean isLeapYear = isLeapYear(year); int oldMonth = ticksToMonths(ticks); return ticks - millisToStartOfMonth(oldMonth, isLeapYear) + millisToStartOfMonth(month, isLeapYear); } /** * Sets the date component of the timestamp, returning the new timestamp with updated component. * * @param ticks The time in ticks. * @param date The new date field. * * @return The new time in ticks. */ public static long ticksWithDateSetTo(long ticks, int date) { int oldDays = ticksToDate(ticks); return ticks - (oldDays * MILLIS_PER_DAY) + (date * MILLIS_PER_DAY); } /** * Calculates the number of milliseconds to the start of the specified year, taking 1970 as zero. * * @param year The year. * * @return The number of milliseconds to the start of the specified year, taking 1970 as zero. */ public static long millisToYearStart(int year) { // Calculate how many leap years elapsed prior to the year in question. int leapYears = year / 100; if (year < 0) { leapYears = ((year + 3) >> 2) - leapYears + ((leapYears + 3) >> 2) - 1; } else { leapYears = (year >> 2) - leapYears + (leapYears >> 2); if (isLeapYear(year)) { leapYears--; } } return ((year * 365L) + leapYears - DAYS_TO_1970) * MILLIS_PER_DAY; } /** * Writes a time of day with milliseconds in the format HH:MM:SS[.sss], into a byte buffer. The specified buffer * will be enlarged if necessary using the specified byte buffer pool. * * @param buffer The initial buffer to write to. * @param value The time of day since midnight, in milliseconds. * * @return The buffer written to. */ public static ByteBuffer putTimeOnlyAsString(ByteBuffer buffer, long value) { buffer = putTimeOnlyAsString(buffer, value, true); return buffer; } /** * Calculate the maximum number of ASCII characters needed to represent a time zone, with or without minutes. * * @param offset The time zone offset. * @param includeMinutes true to include minutes. * * @return The maximum number of ASCII characters needed to represent the time zone. */ public static int getCharacterCountTimeZone(long offset, boolean includeMinutes) { if (offset == 0) { return 1; } else if (includeMinutes) { return TIME_ZONE_WITH_MINUTES_LENGTH; } else { return TIME_ZONE_WITHOUT_MINUTES_LENGTH; } } /** * Writes only the time component of a time of day timestamp to a byte array in the following format: * HH:MM:SS[.sss]. The millisecond value is optional and is only written if requested. If there is insufficient * space in the buffer to write the value into, then the buffer size is increased using the supplied byte buffer * pool. * * @param buffer The byte buffer to write to. * @param value The value to write as a millisecond timestamp. * @param includeMilliseconds true to include milliseconds in the output. * * @return The byte buffer with the value written to it. This may be a different buffer to the one passed in if the * buffer had to be copied in order to increase its size. */ public static ByteBuffer putTimeOnlyAsString(ByteBuffer buffer, long value, boolean includeMilliseconds) { // Ensure there is sufficient space in the buffer for the date. int charsRequired = includeMilliseconds ? TIME_ONLY_LENGTH_WITH_MILLISECONDS : TIME_ONLY_LENGTH_WIHTOUT_MILLISECONDS; buffer = ByteBufferUtils.putPaddedInt32AsString(buffer, ticksToHours(value), 2); buffer = ByteBufferUtils.putByteAsString(buffer, (byte) ':'); buffer = ByteBufferUtils.putPaddedInt32AsString(buffer, ticksToMinutes(value), 2); buffer = ByteBufferUtils.putByteAsString(buffer, (byte) ':'); buffer = ByteBufferUtils.putPaddedInt32AsString(buffer, ticksToSeconds(value), 2); if (includeMilliseconds) { buffer = ByteBufferUtils.putByteAsString(buffer, (byte) '.'); buffer = ByteBufferUtils.putPaddedInt32AsString(buffer, ticksToMilliseconds(value), 3); } return buffer; } /** * Determines whether or not a year is a leap year. This takes no account of when leap years were first introduced, * so will not be accurate for ancient dates. * * @param year The year. * * @return true if the year is a leap year. */ private static boolean isLeapYear(int year) { if ((year & 3) != 0) { return false; } if ((year % 100) != 0) { return true; } return (year % 400) == 0; } /** * Given a millisecond timestamp that lands in a specified year, calculate what month the timestamp corresponds to. * * @param ticks The timestamp. * @param year The year that the timestamp falls in. * * @return The month that the timestamp falls in, in the range 1 to 12. */ private static int getMonthOfYear(long ticks, int year) { int i = (int) ((ticks - millisToYearStart(year)) >> 10); return (isLeapYear(year)) ? ((i < (182 * MILLIS_PER_DAY_OVER_1024)) ? ((i < (91 * MILLIS_PER_DAY_OVER_1024)) ? ((i < (31 * MILLIS_PER_DAY_OVER_1024)) ? 1 : ((i < (60 * MILLIS_PER_DAY_OVER_1024)) ? 2 : 3)) : ((i < (121 * MILLIS_PER_DAY_OVER_1024)) ? 4 : ((i < (152 * MILLIS_PER_DAY_OVER_1024)) ? 5 : 6))) : ((i < (274 * MILLIS_PER_DAY_OVER_1024)) ? ((i < (213 * MILLIS_PER_DAY_OVER_1024)) ? 7 : ((i < (244 * MILLIS_PER_DAY_OVER_1024)) ? 8 : 9)) : ((i < (305 * MILLIS_PER_DAY_OVER_1024)) ? 10 : ((i < (335 * MILLIS_PER_DAY_OVER_1024)) ? 11 : 12)))) : ((i < (181 * MILLIS_PER_DAY_OVER_1024)) ? ((i < (90 * MILLIS_PER_DAY_OVER_1024)) ? ((i < (31 * MILLIS_PER_DAY_OVER_1024)) ? 1 : ((i < (59 * MILLIS_PER_DAY_OVER_1024)) ? 2 : 3)) : ((i < (120 * MILLIS_PER_DAY_OVER_1024)) ? 4 : ((i < (151 * MILLIS_PER_DAY_OVER_1024)) ? 5 : 6))) : ((i < (273 * MILLIS_PER_DAY_OVER_1024)) ? ((i < (212 * MILLIS_PER_DAY_OVER_1024)) ? 7 : ((i < (243 * MILLIS_PER_DAY_OVER_1024)) ? 8 : 9)) : ((i < (304 * MILLIS_PER_DAY_OVER_1024)) ? 10 : ((i < (334 * MILLIS_PER_DAY_OVER_1024)) ? 11 : 12)))); } /** * Given a month, numbered from 1 to 12, calculates the number of milliseconds to the start of that month in a year. * * @param month The month. * @param leapYear true if the year is a leap year. * * @return The number of milliseconds to the start of the month. */ private static long millisToStartOfMonth(int month, boolean leapYear) { return (long) (leapYear ? LEAP_DAYS_IN_YEAR_PRIOR_TO_MONTH[month - 1] : USUAL_DAYS_IN_YEAR_PRIOR_TO_MONTH[month - 1]) * MILLIS_PER_DAY; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy