package goja

import (
	
	
	
)

const (
	dateTimeLayout       = "Mon Jan 02 2006 15:04:05 GMT-0700 (MST)"
	utcDateTimeLayout    = "Mon, 02 Jan 2006 15:04:05 GMT"
	isoDateTimeLayout    = "2006-01-02T15:04:05.000Z"
	dateLayout           = "Mon Jan 02 2006"
	timeLayout           = "15:04:05 GMT-0700 (MST)"
	datetimeLayout_en_GB = "01/02/2006, 15:04:05"
	dateLayout_en_GB     = "01/02/2006"
	timeLayout_en_GB     = "15:04:05"

	maxTime   = 8.64e15
	timeUnset = math.MinInt64
)

type dateObject struct {
	baseObject
	msec int64
}

func dateParse( string) ( time.Time,  bool) {
	,  := parseDateISOString()
	if ! {
		,  = parseDateOtherString()
	}
	if ! {
		return
	}
	if .month > 12 ||
		.day > 31 ||
		.hour > 24 ||
		.min > 59 ||
		.sec > 59 ||
		// special case 24:00:00.000
		(.hour == 24 && (.min != 0 || .sec != 0 || .msec != 0)) {
		 = false
		return
	}
	var  *time.Location
	if .isLocal {
		 = time.Local
	} else {
		 = time.FixedZone("", .timeZoneOffset*60)
	}
	 = time.Date(.year, time.Month(.month), .day, .hour, .min, .sec, .msec*1e6, )
	 := .UnixMilli()
	 =  >= -maxTime &&  <= maxTime
	return
}

func ( *Runtime) ( time.Time,  bool,  *Object) *Object {
	 := &Object{runtime: }
	 := &dateObject{}
	.self = 
	.val = 
	.class = classDate
	.prototype = 
	.extensible = true
	.init()
	if  {
		.msec = timeToMsec()
	} else {
		.msec = timeUnset
	}
	return 
}

func dateFormat( time.Time) string {
	return .Local().Format(dateTimeLayout)
}

func timeFromMsec( int64) time.Time {
	 :=  / 1000
	 := ( % 1000) * 1e6
	return time.Unix(, )
}

func timeToMsec( time.Time) int64 {
	return .Unix()*1000 + int64(.Nanosecond())/1e6
}

func ( *dateObject) () reflect.Type {
	return typeTime
}

func ( *dateObject) (*objectExportCtx) interface{} {
	if .isSet() {
		return .time()
	}
	return nil
}

func ( *dateObject) ( int64) Value {
	if  >= 0 &&  <= maxTime ||  < 0 &&  >= -maxTime {
		.msec = 
		return intToValue()
	}

	.unset()
	return _NaN
}

func ( *dateObject) () bool {
	return .msec != timeUnset
}

func ( *dateObject) () {
	.msec = timeUnset
}

func ( *dateObject) () time.Time {
	return timeFromMsec(.msec)
}

func ( *dateObject) () time.Time {
	return timeFromMsec(.msec).In(time.UTC)
}