1package otto 2 3import ( 4 "math" 5 Time "time" 6) 7 8// Date 9 10const ( 11 // TODO Be like V8? 12 // builtinDate_goDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)" 13 builtinDate_goDateTimeLayout = Time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST" 14 builtinDate_goDateLayout = "Mon, 02 Jan 2006" 15 builtinDate_goTimeLayout = "15:04:05 MST" 16) 17 18func builtinDate(call FunctionCall) Value { 19 date := &_dateObject{} 20 date.Set(newDateTime([]Value{}, Time.Local)) 21 return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout)) 22} 23 24func builtinNewDate(self *_object, argumentList []Value) Value { 25 return toValue_object(self.runtime.newDate(newDateTime(argumentList, Time.Local))) 26} 27 28func builtinDate_toString(call FunctionCall) Value { 29 date := dateObjectOf(call.runtime, call.thisObject()) 30 if date.isNaN { 31 return toValue_string("Invalid Date") 32 } 33 return toValue_string(date.Time().Local().Format(builtinDate_goDateTimeLayout)) 34} 35 36func builtinDate_toDateString(call FunctionCall) Value { 37 date := dateObjectOf(call.runtime, call.thisObject()) 38 if date.isNaN { 39 return toValue_string("Invalid Date") 40 } 41 return toValue_string(date.Time().Local().Format(builtinDate_goDateLayout)) 42} 43 44func builtinDate_toTimeString(call FunctionCall) Value { 45 date := dateObjectOf(call.runtime, call.thisObject()) 46 if date.isNaN { 47 return toValue_string("Invalid Date") 48 } 49 return toValue_string(date.Time().Local().Format(builtinDate_goTimeLayout)) 50} 51 52func builtinDate_toUTCString(call FunctionCall) Value { 53 date := dateObjectOf(call.runtime, call.thisObject()) 54 if date.isNaN { 55 return toValue_string("Invalid Date") 56 } 57 return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout)) 58} 59 60func builtinDate_toISOString(call FunctionCall) Value { 61 date := dateObjectOf(call.runtime, call.thisObject()) 62 if date.isNaN { 63 return toValue_string("Invalid Date") 64 } 65 return toValue_string(date.Time().Format("2006-01-02T15:04:05.000Z")) 66} 67 68func builtinDate_toJSON(call FunctionCall) Value { 69 object := call.thisObject() 70 value := object.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue 71 { // FIXME value.isFinite 72 value := value.float64() 73 if math.IsNaN(value) || math.IsInf(value, 0) { 74 return nullValue 75 } 76 } 77 toISOString := object.get("toISOString") 78 if !toISOString.isCallable() { 79 // FIXME 80 panic(call.runtime.panicTypeError()) 81 } 82 return toISOString.call(call.runtime, toValue_object(object), []Value{}) 83} 84 85func builtinDate_toGMTString(call FunctionCall) Value { 86 date := dateObjectOf(call.runtime, call.thisObject()) 87 if date.isNaN { 88 return toValue_string("Invalid Date") 89 } 90 return toValue_string(date.Time().Format("Mon, 02 Jan 2006 15:04:05 GMT")) 91} 92 93func builtinDate_getTime(call FunctionCall) Value { 94 date := dateObjectOf(call.runtime, call.thisObject()) 95 if date.isNaN { 96 return NaNValue() 97 } 98 // We do this (convert away from a float) so the user 99 // does not get something back in exponential notation 100 return toValue_int64(int64(date.Epoch())) 101} 102 103func builtinDate_setTime(call FunctionCall) Value { 104 object := call.thisObject() 105 date := dateObjectOf(call.runtime, call.thisObject()) 106 date.Set(call.Argument(0).float64()) 107 object.value = date 108 return date.Value() 109} 110 111func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*_object, *_dateObject, *_ecmaTime, []int) { 112 object := call.thisObject() 113 date := dateObjectOf(call.runtime, call.thisObject()) 114 if date.isNaN { 115 return nil, nil, nil, nil 116 } 117 118 if argumentLimit > len(call.ArgumentList) { 119 argumentLimit = len(call.ArgumentList) 120 } 121 122 if argumentLimit == 0 { 123 object.value = invalidDateObject 124 return nil, nil, nil, nil 125 } 126 127 valueList := make([]int, argumentLimit) 128 for index := 0; index < argumentLimit; index++ { 129 value := call.ArgumentList[index] 130 nm := value.number() 131 switch nm.kind { 132 case numberInteger, numberFloat: 133 default: 134 object.value = invalidDateObject 135 return nil, nil, nil, nil 136 } 137 valueList[index] = int(nm.int64) 138 } 139 baseTime := date.Time() 140 if timeLocal { 141 baseTime = baseTime.Local() 142 } 143 ecmaTime := ecmaTime(baseTime) 144 return object, &date, &ecmaTime, valueList 145} 146 147func builtinDate_parse(call FunctionCall) Value { 148 date := call.Argument(0).string() 149 return toValue_float64(dateParse(date)) 150} 151 152func builtinDate_UTC(call FunctionCall) Value { 153 return toValue_float64(newDateTime(call.ArgumentList, Time.UTC)) 154} 155 156func builtinDate_now(call FunctionCall) Value { 157 call.ArgumentList = []Value(nil) 158 return builtinDate_UTC(call) 159} 160 161// This is a placeholder 162func builtinDate_toLocaleString(call FunctionCall) Value { 163 date := dateObjectOf(call.runtime, call.thisObject()) 164 if date.isNaN { 165 return toValue_string("Invalid Date") 166 } 167 return toValue_string(date.Time().Local().Format("2006-01-02 15:04:05")) 168} 169 170// This is a placeholder 171func builtinDate_toLocaleDateString(call FunctionCall) Value { 172 date := dateObjectOf(call.runtime, call.thisObject()) 173 if date.isNaN { 174 return toValue_string("Invalid Date") 175 } 176 return toValue_string(date.Time().Local().Format("2006-01-02")) 177} 178 179// This is a placeholder 180func builtinDate_toLocaleTimeString(call FunctionCall) Value { 181 date := dateObjectOf(call.runtime, call.thisObject()) 182 if date.isNaN { 183 return toValue_string("Invalid Date") 184 } 185 return toValue_string(date.Time().Local().Format("15:04:05")) 186} 187 188func builtinDate_valueOf(call FunctionCall) Value { 189 date := dateObjectOf(call.runtime, call.thisObject()) 190 if date.isNaN { 191 return NaNValue() 192 } 193 return date.Value() 194} 195 196func builtinDate_getYear(call FunctionCall) Value { 197 // Will throw a TypeError is ThisObject is nil or 198 // does not have Class of "Date" 199 date := dateObjectOf(call.runtime, call.thisObject()) 200 if date.isNaN { 201 return NaNValue() 202 } 203 return toValue_int(date.Time().Local().Year() - 1900) 204} 205 206func builtinDate_getFullYear(call FunctionCall) Value { 207 // Will throw a TypeError is ThisObject is nil or 208 // does not have Class of "Date" 209 date := dateObjectOf(call.runtime, call.thisObject()) 210 if date.isNaN { 211 return NaNValue() 212 } 213 return toValue_int(date.Time().Local().Year()) 214} 215 216func builtinDate_getUTCFullYear(call FunctionCall) Value { 217 date := dateObjectOf(call.runtime, call.thisObject()) 218 if date.isNaN { 219 return NaNValue() 220 } 221 return toValue_int(date.Time().Year()) 222} 223 224func builtinDate_getMonth(call FunctionCall) Value { 225 date := dateObjectOf(call.runtime, call.thisObject()) 226 if date.isNaN { 227 return NaNValue() 228 } 229 return toValue_int(dateFromGoMonth(date.Time().Local().Month())) 230} 231 232func builtinDate_getUTCMonth(call FunctionCall) Value { 233 date := dateObjectOf(call.runtime, call.thisObject()) 234 if date.isNaN { 235 return NaNValue() 236 } 237 return toValue_int(dateFromGoMonth(date.Time().Month())) 238} 239 240func builtinDate_getDate(call FunctionCall) Value { 241 date := dateObjectOf(call.runtime, call.thisObject()) 242 if date.isNaN { 243 return NaNValue() 244 } 245 return toValue_int(date.Time().Local().Day()) 246} 247 248func builtinDate_getUTCDate(call FunctionCall) Value { 249 date := dateObjectOf(call.runtime, call.thisObject()) 250 if date.isNaN { 251 return NaNValue() 252 } 253 return toValue_int(date.Time().Day()) 254} 255 256func builtinDate_getDay(call FunctionCall) Value { 257 // Actually day of the week 258 date := dateObjectOf(call.runtime, call.thisObject()) 259 if date.isNaN { 260 return NaNValue() 261 } 262 return toValue_int(dateFromGoDay(date.Time().Local().Weekday())) 263} 264 265func builtinDate_getUTCDay(call FunctionCall) Value { 266 date := dateObjectOf(call.runtime, call.thisObject()) 267 if date.isNaN { 268 return NaNValue() 269 } 270 return toValue_int(dateFromGoDay(date.Time().Weekday())) 271} 272 273func builtinDate_getHours(call FunctionCall) Value { 274 date := dateObjectOf(call.runtime, call.thisObject()) 275 if date.isNaN { 276 return NaNValue() 277 } 278 return toValue_int(date.Time().Local().Hour()) 279} 280 281func builtinDate_getUTCHours(call FunctionCall) Value { 282 date := dateObjectOf(call.runtime, call.thisObject()) 283 if date.isNaN { 284 return NaNValue() 285 } 286 return toValue_int(date.Time().Hour()) 287} 288 289func builtinDate_getMinutes(call FunctionCall) Value { 290 date := dateObjectOf(call.runtime, call.thisObject()) 291 if date.isNaN { 292 return NaNValue() 293 } 294 return toValue_int(date.Time().Local().Minute()) 295} 296 297func builtinDate_getUTCMinutes(call FunctionCall) Value { 298 date := dateObjectOf(call.runtime, call.thisObject()) 299 if date.isNaN { 300 return NaNValue() 301 } 302 return toValue_int(date.Time().Minute()) 303} 304 305func builtinDate_getSeconds(call FunctionCall) Value { 306 date := dateObjectOf(call.runtime, call.thisObject()) 307 if date.isNaN { 308 return NaNValue() 309 } 310 return toValue_int(date.Time().Local().Second()) 311} 312 313func builtinDate_getUTCSeconds(call FunctionCall) Value { 314 date := dateObjectOf(call.runtime, call.thisObject()) 315 if date.isNaN { 316 return NaNValue() 317 } 318 return toValue_int(date.Time().Second()) 319} 320 321func builtinDate_getMilliseconds(call FunctionCall) Value { 322 date := dateObjectOf(call.runtime, call.thisObject()) 323 if date.isNaN { 324 return NaNValue() 325 } 326 return toValue_int(date.Time().Local().Nanosecond() / (100 * 100 * 100)) 327} 328 329func builtinDate_getUTCMilliseconds(call FunctionCall) Value { 330 date := dateObjectOf(call.runtime, call.thisObject()) 331 if date.isNaN { 332 return NaNValue() 333 } 334 return toValue_int(date.Time().Nanosecond() / (100 * 100 * 100)) 335} 336 337func builtinDate_getTimezoneOffset(call FunctionCall) Value { 338 date := dateObjectOf(call.runtime, call.thisObject()) 339 if date.isNaN { 340 return NaNValue() 341 } 342 timeLocal := date.Time().Local() 343 // Is this kosher? 344 timeLocalAsUTC := Time.Date( 345 timeLocal.Year(), 346 timeLocal.Month(), 347 timeLocal.Day(), 348 timeLocal.Hour(), 349 timeLocal.Minute(), 350 timeLocal.Second(), 351 timeLocal.Nanosecond(), 352 Time.UTC, 353 ) 354 return toValue_float64(date.Time().Sub(timeLocalAsUTC).Seconds() / 60) 355} 356 357func builtinDate_setMilliseconds(call FunctionCall) Value { 358 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) 359 if ecmaTime == nil { 360 return NaNValue() 361 } 362 363 ecmaTime.millisecond = value[0] 364 365 date.SetTime(ecmaTime.goTime()) 366 object.value = *date 367 return date.Value() 368} 369 370func builtinDate_setUTCMilliseconds(call FunctionCall) Value { 371 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false) 372 if ecmaTime == nil { 373 return NaNValue() 374 } 375 376 ecmaTime.millisecond = value[0] 377 378 date.SetTime(ecmaTime.goTime()) 379 object.value = *date 380 return date.Value() 381} 382 383func builtinDate_setSeconds(call FunctionCall) Value { 384 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true) 385 if ecmaTime == nil { 386 return NaNValue() 387 } 388 389 if len(value) > 1 { 390 ecmaTime.millisecond = value[1] 391 } 392 ecmaTime.second = value[0] 393 394 date.SetTime(ecmaTime.goTime()) 395 object.value = *date 396 return date.Value() 397} 398 399func builtinDate_setUTCSeconds(call FunctionCall) Value { 400 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false) 401 if ecmaTime == nil { 402 return NaNValue() 403 } 404 405 if len(value) > 1 { 406 ecmaTime.millisecond = value[1] 407 } 408 ecmaTime.second = value[0] 409 410 date.SetTime(ecmaTime.goTime()) 411 object.value = *date 412 return date.Value() 413} 414 415func builtinDate_setMinutes(call FunctionCall) Value { 416 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true) 417 if ecmaTime == nil { 418 return NaNValue() 419 } 420 421 if len(value) > 2 { 422 ecmaTime.millisecond = value[2] 423 ecmaTime.second = value[1] 424 } else if len(value) > 1 { 425 ecmaTime.second = value[1] 426 } 427 ecmaTime.minute = value[0] 428 429 date.SetTime(ecmaTime.goTime()) 430 object.value = *date 431 return date.Value() 432} 433 434func builtinDate_setUTCMinutes(call FunctionCall) Value { 435 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false) 436 if ecmaTime == nil { 437 return NaNValue() 438 } 439 440 if len(value) > 2 { 441 ecmaTime.millisecond = value[2] 442 ecmaTime.second = value[1] 443 } else if len(value) > 1 { 444 ecmaTime.second = value[1] 445 } 446 ecmaTime.minute = value[0] 447 448 date.SetTime(ecmaTime.goTime()) 449 object.value = *date 450 return date.Value() 451} 452 453func builtinDate_setHours(call FunctionCall) Value { 454 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, true) 455 if ecmaTime == nil { 456 return NaNValue() 457 } 458 459 if len(value) > 3 { 460 ecmaTime.millisecond = value[3] 461 ecmaTime.second = value[2] 462 ecmaTime.minute = value[1] 463 } else if len(value) > 2 { 464 ecmaTime.second = value[2] 465 ecmaTime.minute = value[1] 466 } else if len(value) > 1 { 467 ecmaTime.minute = value[1] 468 } 469 ecmaTime.hour = value[0] 470 471 date.SetTime(ecmaTime.goTime()) 472 object.value = *date 473 return date.Value() 474} 475 476func builtinDate_setUTCHours(call FunctionCall) Value { 477 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, false) 478 if ecmaTime == nil { 479 return NaNValue() 480 } 481 482 if len(value) > 3 { 483 ecmaTime.millisecond = value[3] 484 ecmaTime.second = value[2] 485 ecmaTime.minute = value[1] 486 } else if len(value) > 2 { 487 ecmaTime.second = value[2] 488 ecmaTime.minute = value[1] 489 } else if len(value) > 1 { 490 ecmaTime.minute = value[1] 491 } 492 ecmaTime.hour = value[0] 493 494 date.SetTime(ecmaTime.goTime()) 495 object.value = *date 496 return date.Value() 497} 498 499func builtinDate_setDate(call FunctionCall) Value { 500 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) 501 if ecmaTime == nil { 502 return NaNValue() 503 } 504 505 ecmaTime.day = value[0] 506 507 date.SetTime(ecmaTime.goTime()) 508 object.value = *date 509 return date.Value() 510} 511 512func builtinDate_setUTCDate(call FunctionCall) Value { 513 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false) 514 if ecmaTime == nil { 515 return NaNValue() 516 } 517 518 ecmaTime.day = value[0] 519 520 date.SetTime(ecmaTime.goTime()) 521 object.value = *date 522 return date.Value() 523} 524 525func builtinDate_setMonth(call FunctionCall) Value { 526 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true) 527 if ecmaTime == nil { 528 return NaNValue() 529 } 530 531 if len(value) > 1 { 532 ecmaTime.day = value[1] 533 } 534 ecmaTime.month = value[0] 535 536 date.SetTime(ecmaTime.goTime()) 537 object.value = *date 538 return date.Value() 539} 540 541func builtinDate_setUTCMonth(call FunctionCall) Value { 542 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false) 543 if ecmaTime == nil { 544 return NaNValue() 545 } 546 547 if len(value) > 1 { 548 ecmaTime.day = value[1] 549 } 550 ecmaTime.month = value[0] 551 552 date.SetTime(ecmaTime.goTime()) 553 object.value = *date 554 return date.Value() 555} 556 557func builtinDate_setYear(call FunctionCall) Value { 558 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) 559 if ecmaTime == nil { 560 return NaNValue() 561 } 562 563 year := value[0] 564 if 0 <= year && year <= 99 { 565 year += 1900 566 } 567 ecmaTime.year = year 568 569 date.SetTime(ecmaTime.goTime()) 570 object.value = *date 571 return date.Value() 572} 573 574func builtinDate_setFullYear(call FunctionCall) Value { 575 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true) 576 if ecmaTime == nil { 577 return NaNValue() 578 } 579 580 if len(value) > 2 { 581 ecmaTime.day = value[2] 582 ecmaTime.month = value[1] 583 } else if len(value) > 1 { 584 ecmaTime.month = value[1] 585 } 586 ecmaTime.year = value[0] 587 588 date.SetTime(ecmaTime.goTime()) 589 object.value = *date 590 return date.Value() 591} 592 593func builtinDate_setUTCFullYear(call FunctionCall) Value { 594 object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false) 595 if ecmaTime == nil { 596 return NaNValue() 597 } 598 599 if len(value) > 2 { 600 ecmaTime.day = value[2] 601 ecmaTime.month = value[1] 602 } else if len(value) > 1 { 603 ecmaTime.month = value[1] 604 } 605 ecmaTime.year = value[0] 606 607 date.SetTime(ecmaTime.goTime()) 608 object.value = *date 609 return date.Value() 610} 611 612// toUTCString 613// toISOString 614// toJSONString 615// toJSON 616