import { differenceInCalendarDays , differenceInCalendarMonths , differenceInCalendarYears , differenceInWeeks , differenceInHours , differenceInMinutes , differenceInSeconds , isSameDay , isSameHour , isSameMinute , isSameMonth , isSameSecond , isSameYear , isToday , isTomorrow , isValid , setYear , startOfMonth , startOfWeek , addMonths , addYears , setDay , setMonth , getUnixTime , startOfDay , endOfDay , fromUnixTime , isWeekend , getWeek , getDaysInMonth , addSeconds , addMinutes , addHours , addWeeks , addQuarters , startOfQuarter , startOfYear , endOfWeek , endOfMonth , endOfQuarter , endOfYear , format , getQuarter , addDays } from './functions' ; import { Locale } from 'date-fns' ; export type TinyDateCompareGrain = 'decade' | 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' ; export type WeekDayIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6 ; export type TinyDateType = TinyDate | Date | null ; export function sortRangeValue ( rangeValue ) { if ( Array . isArray ( rangeValue ) ) { const [ start , end ] = rangeValue ; return start && end && start . isAfterSecond ( end ) ? [ end , start ] : [ start , end ] ; } return rangeValue ; } export class TinyDate implements Record < string , any > { nativeDate : Date ; constructor ( date ? ) { if ( date ) { if ( date instanceof Date ) { this . nativeDate = date ; } else if ( typeof date === 'string' || typeof date === 'number' ) { this . nativeDate = new Date ( date ) ; } else { throw new Error ( `The input date type is not supported expect Date | string | number | { date: number; with_time: 0 | 1}, actual ${ JSON . stringify ( date ) }` ) ; } } else { this . nativeDate = new Date ( ) ; } } static fromUnixTime ( unixTime ) { return new TinyDate ( fromUnixTime ( unixTime ) ) ; } getTime ( ) { return this . nativeDate . getTime ( ) ; } getDate ( ) { return this . nativeDate . getDate ( ) ; } getYear ( ) { return this . nativeDate . getFullYear ( ) ; } getQuarter ( ) { return getQuarter ( this . nativeDate ) ; } getMonth ( ) { return this . nativeDate . getMonth ( ) ; } getWeek ( options = { weekStartsOn : 1 } ) { return getWeek ( this . nativeDate , options ) ; } getDay ( ) { return this . nativeDate . getDay ( ) ; } getHours ( ) { return this . nativeDate . getHours ( ) ; } getMinutes ( ) { return this . nativeDate . getMinutes ( ) ; } getSeconds ( ) { return this . nativeDate . getSeconds ( ) ; } getMilliseconds ( ) { return this . nativeDate . getMilliseconds ( ) ; } getDaysInMonth ( ) { return getDaysInMonth ( this . nativeDate ) ; } getDaysInQuarter ( ) { return differenceInCalendarDays ( this . endOfQuarter ( ) . addSeconds ( 1 ) . nativeDate , this . startOfQuarter ( ) . nativeDate ) ; } setDate ( amount ) { const date = new Date ( this . nativeDate ) ; date . setDate ( amount ) ; return new TinyDate ( date ) ; } setHms ( hour , minute , second ) { const date = new Date ( this . nativeDate ) ; date . setHours ( hour , minute , second ) ; return new TinyDate ( date ) ; } setYear ( year ) { return new TinyDate ( setYear ( this . nativeDate , year ) ) ; } setMonth ( month ) { return new TinyDate ( setMonth ( this . nativeDate , month ) ) ; } setDay ( day , options ? ) { return new TinyDate ( setDay ( this . nativeDate , day , options ) ) ; } addYears ( amount ) { return new TinyDate ( addYears ( this . nativeDate , amount ) ) ; } addQuarters ( amount ) { return new TinyDate ( addQuarters ( this . nativeDate , amount ) ) ; } addMonths ( amount ) { return new TinyDate ( addMonths ( this . nativeDate , amount ) ) ; } addWeeks ( amount ) { return new TinyDate ( addWeeks ( this . nativeDate , amount ) ) ; } addDays ( amount ) { return new TinyDate ( addDays ( this . nativeDate , amount ) ) ; } addHours ( amount ) { return new TinyDate ( addHours ( this . nativeDate , amount ) ) ; } addSeconds ( amount ) { return new TinyDate ( addSeconds ( this . nativeDate , amount ) ) ; } addMinutes ( amount ) { return new TinyDate ( addMinutes ( this . nativeDate , amount ) ) ; } isSame ( date , grain = 'day' ) { let fn ; switch ( grain ) { case 'decade' : fn = ( pre , next ) => Math . abs ( pre . getFullYear ( ) - next . getFullYear ( ) ) < 11 ; break ; case 'year' : fn = isSameYear ; break ; case 'month' : fn = isSameMonth ; break ; case 'day' : fn = isSameDay ; break ; case 'hour' : fn = isSameHour ; break ; case 'minute' : fn = isSameMinute ; break ; case 'second' : fn = isSameSecond ; break ; default : fn = isSameDay ; break ; } return fn ( this . nativeDate , this . toNativeDate ( date ) ) ; } isSameYear ( date ) { return this . isSame ( date , 'year' ) ; } isSameMonth ( date ) { return this . isSame ( date , 'month' ) ; } isSameDay ( date ) { return this . isSame ( date , 'day' ) ; } isSameHour ( date ) { return this . isSame ( date , 'hour' ) ; } isSameMinute ( date ) { return this . isSame ( date , 'minute' ) ; } isSameSecond ( date ) { return this . isSame ( date , 'second' ) ; } isBeforeYear ( date ) { return this . compare ( date , 'year' ) ; } isBeforeMonth ( date ) { return this . compare ( date , 'month' ) ; } isBeforeWeek ( date ) { return this . compare ( date , 'week' ) ; } isBeforeDay ( date ) { return this . compare ( date , 'day' ) ; } isBeforeHour ( date ) { return this . compare ( date , 'hour' ) ; } isBeforeMinute ( date ) { return this . compare ( date , 'minute' ) ; } isBeforeSecond ( date ) { return this . compare ( date , 'second' ) ; } isAfterYear ( date ) { return this . compare ( date , 'year' , false ) ; } isAfterMonth ( date ) { return this . compare ( date , 'month' , false ) ; } isAfterWeek ( date ) { return this . compare ( date , 'week' , false ) ; } isAfterDay ( date ) { return this . compare ( date , 'day' , false ) ; } isAfterHour ( date ) { return this . compare ( date , 'hour' , false ) ; } isAfterMinute ( date ) { return this . compare ( date , 'minute' , false ) ; } isAfterSecond ( date ) { return this . compare ( date , 'second' , false ) ; } isWeekend ( ) { return isWeekend ( this . nativeDate ) ; } isToday ( ) { return isToday ( this . nativeDate ) ; } isTomorrow ( ) { return isTomorrow ( this . nativeDate ) ; } isValid ( ) { return isValid ( this . nativeDate ) ; } startOfYear ( ) { return new TinyDate ( startOfYear ( this . nativeDate ) ) ; } startOfQuarter ( ) { return new TinyDate ( startOfQuarter ( this . nativeDate ) ) ; } startOfMonth ( ) { return new TinyDate ( startOfMonth ( this . nativeDate ) ) ; } startOfWeek ( options ? ) { return new TinyDate ( startOfWeek ( this . nativeDate , options ) ) ; } startOfDay ( ) { return new TinyDate ( startOfDay ( this . nativeDate ) ) ; } endOfYear ( ) { return new TinyDate ( endOfYear ( this . nativeDate ) ) ; } endOfQuarter ( ) { return new TinyDate ( endOfQuarter ( this . nativeDate ) ) ; } endOfMonth ( ) { return new TinyDate ( endOfMonth ( this . nativeDate ) ) ; } endOfWeek ( options ? ) { return new TinyDate ( endOfWeek ( this . nativeDate , options ) ) ; } endOfDay ( ) { return new TinyDate ( endOfDay ( this . nativeDate ) ) ; } format ( mat , options ? ) { return format ( this . nativeDate , mat , options ) ; } calendarStart ( options ? ) { return new TinyDate ( startOfWeek ( startOfMonth ( this . nativeDate ) , options ) ) ; } clone ( ) { return new TinyDate ( new Date ( this . nativeDate ) ) ; } getUnixTime ( ) { return getUnixTime ( this . nativeDate ) ; } compare ( date , grain = 'day' , isBefore = true ) { if ( date === null ) { return false ; } let fn ; switch ( grain ) { case 'year' : fn = differenceInCalendarYears ; break ; case 'month' : fn = differenceInCalendarMonths ; break ; case 'day' : fn = differenceInCalendarDays ; break ; case 'week' : fn = differenceInWeeks ; break ; case 'hour' : fn = differenceInHours ; break ; case 'minute' : fn = differenceInMinutes ; break ; case 'second' : fn = differenceInSeconds ; break ; default : fn = differenceInCalendarDays ; break ; } return isBefore ? fn ( this . nativeDate , this . toNativeDate ( date ) ) < 0 : fn ( this . nativeDate , this . toNativeDate ( date ) ) > 0 ; } private toNativeDate ( date ) { return date instanceof TinyDate ? date . nativeDate : date ; } }