2005-11-24 Chris Toshok <toshok@ximian.com>
[mono.git] / mcs / class / Microsoft.JScript / Microsoft.JScript / DatePrototype.cs
1 //
2 // DataPrototype.cs:
3 //
4 // Author:
5 //      Cesar Lopez Nataren (cesar@ciencias.unam.mx)
6 //
7 // (C) Cesar Lopez Nataren
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Globalization;
33
34 namespace Microsoft.JScript {
35
36         public class DatePrototype : DateObject
37         {
38                 internal DatePrototype ()
39                         : base (Double.NaN)
40                 {
41                 }
42
43                 internal static DatePrototype Proto = new DatePrototype ();
44
45                 public static DateConstructor constructor {
46                         get { return DateConstructor.Ctr; }
47                 }
48
49                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getDate)]
50                 public static double getDate (object thisObj)
51                 {
52                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
53
54                         DateObject date = (DateObject) thisObj;
55                         double val = date.ms;
56
57                         if (Double.IsNaN (val))
58                                 return Double.NaN;
59                         else
60                                 return DateConstructor.DateFromTime (DateConstructor.LocalTime (val));
61                 }
62
63                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getDay)]
64                 public static double getDay (object thisObj)
65                 {
66                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
67
68                         DateObject date = (DateObject) thisObj;
69                         double val = date.ms;
70
71                         if (Double.IsNaN (val))
72                                 return Double.NaN;
73                         else
74                                 return DateConstructor.WeekDay (DateConstructor.LocalTime (val));
75                 }
76
77                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getFullYear)]
78                 public static double getFullYear (object thisObj)
79                 {
80                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
81
82                         DateObject date = (DateObject) thisObj;
83                         double val = date.ms;
84
85                         if (Double.IsNaN (val))
86                                 return Double.NaN;
87                         else
88                                 return DateConstructor.YearFromTime (DateConstructor.LocalTime (val));
89                 }
90
91                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getHours)]
92                 public static double getHours (object thisObj)
93                 {
94                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
95
96                         DateObject date = (DateObject) thisObj;
97                         double val = date.ms;
98                         
99                         if (Double.IsNaN (val))
100                                 return Double.NaN;
101                         else
102                                 return DateConstructor.HourFromTime (DateConstructor.LocalTime (val));
103                 }
104
105                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getMilliseconds)]
106                 public static double getMilliseconds (object thisObj)
107                 {
108                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
109
110                         DateObject date = (DateObject) thisObj;
111                         double val = date.ms;
112
113                         if (Double.IsNaN (val))
114                                 return Double.NaN;
115                         else
116                                 return DateConstructor.msFromTime (DateConstructor.LocalTime (val));
117                 }
118
119                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getMinutes)]
120                 public static double getMinutes (object thisObj)
121                 {
122                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
123
124                         DateObject date = (DateObject) thisObj;
125                         double val = date.ms;
126
127                         if (Double.IsNaN (val))
128                                 return Double.NaN;
129                         else
130                                 return DateConstructor.MinFromTime (DateConstructor.LocalTime (val));
131                 }
132
133                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getMonth)]
134                 public static double getMonth (object thisObj)
135                 {
136                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
137
138                         DateObject date = (DateObject) thisObj;
139                         double val = date.ms;
140
141                         if (Double.IsNaN (val))
142                                 return Double.NaN;
143                         else
144                                 return DateConstructor.MonthFromTime (DateConstructor.LocalTime (val));
145                 }
146
147                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getSeconds)]
148                 public static double getSeconds (object thisObj)
149                 {
150                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
151
152                         DateObject date = (DateObject) thisObj;
153                         double val = date.ms;
154
155                         if (Double.IsNaN (val))
156                                 return Double.NaN;
157                         else
158                                 return DateConstructor.SecFromTime (DateConstructor.LocalTime (val));
159                 }
160
161                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getTime)]
162                 public static double getTime (object thisObj)
163                 {
164                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
165                         DateObject date = (DateObject) thisObj;
166                         return date.ms;
167                 }
168
169                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getTimezoneOffset)]
170                 public static double getTimezoneOffset (object thisObj)
171                 {
172                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
173
174                         DateObject date = (DateObject) thisObj;
175                         double val = date.ms;
176
177                         if (Double.IsNaN (val))
178                                 return Double.NaN;
179                         else 
180                                 return (val - DateConstructor.LocalTime (val)) / DateConstructor.MS_PER_MINUTE;
181                 }
182
183                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getUTCDate)]
184                 public static double getUTCDate (object thisObj)
185                 {
186                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
187
188                         DateObject date = (DateObject) thisObj;
189                         double val = date.ms;
190
191                         if (Double.IsNaN (val))
192                                 return Double.NaN;
193                         else
194                                 return DateConstructor.DateFromTime (val);
195                 }
196
197                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getUTCDay)]
198                 public static double getUTCDay (object thisObj)
199                 {
200                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
201
202                         DateObject date = (DateObject) thisObj;
203                         double val = date.ms;
204
205                         if (Double.IsNaN (val))
206                                 return Double.NaN;
207                         else
208                                 return DateConstructor.WeekDay (val);
209                 }
210
211                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getUTCFullYear)]
212                 public static double getUTCFullYear (object thisObj)
213                 {
214                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
215
216                         DateObject date = (DateObject) thisObj;
217                         double val = date.ms;
218
219                         if (Double.IsNaN (val))
220                                 return Double.NaN;
221                         else
222                                 return DateConstructor.YearFromTime (val);
223                 }
224
225                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getUTCHours)]
226                 public static double getUTCHours (object thisObj)
227                 {
228                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
229
230                         DateObject date = (DateObject) thisObj;
231                         double val = date.ms;
232
233                         if (Double.IsNaN (val))
234                                 return Double.NaN;
235                         else
236                                 return DateConstructor.HourFromTime (val);
237                 }
238
239                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getUTCMilliseconds)]
240                 public static double getUTCMilliseconds (object thisObj)
241                 {
242                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
243
244                         DateObject date = (DateObject) thisObj;
245                         double val = date.ms;
246
247                         if (Double.IsNaN (val))
248                                 return Double.NaN;
249                         else
250                                 return DateConstructor.msFromTime (val);
251                 }
252
253                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getUTCMinutes)]
254                 public static double getUTCMinutes (object thisObj)
255                 {
256                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
257
258                         DateObject date = (DateObject) thisObj;
259                         double val = date.ms;
260
261                         if (Double.IsNaN (val))
262                                 return Double.NaN;
263                         else
264                                 return DateConstructor.MinFromTime (val);
265                 }
266
267                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getUTCMonth)]
268                 public static double getUTCMonth (object thisObj)
269                 {
270                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
271
272                         DateObject date = (DateObject) thisObj;
273                         double val = date.ms;
274
275                         if (Double.IsNaN (val))
276                                 return Double.NaN;
277                         else
278                                 return DateConstructor.MonthFromTime (val);
279                 }
280
281                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getUTCSeconds)]
282                 public static double getUTCSeconds (object thisObj)
283                 {
284                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
285
286                         DateObject date = (DateObject) thisObj;
287                         double val = date.ms;
288
289                         if (Double.IsNaN (val))
290                                 return Double.NaN;
291                         else
292                                 return DateConstructor.SecFromTime (val);
293                 }
294
295                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getVarDate)]
296                 public static object getVarDate (object thisObj)
297                 {
298                         //
299                         // FIXME: This seems to handle the most simple
300                         // cases, but surely we need to do more
301                         // to comply with Microsoft's implementation.
302                         //
303                         return thisObj;
304                 }
305
306                 //
307                 // Note: This method is obsolete, but users might
308                 // accidently use it instead of getFullYear(). The
309                 // standard says to return the year - 1900 (likely for
310                 // compatibility), but in this case not confusing the
311                 // user's expectations is more important than not
312                 // breaking obsolete code.
313                 //
314                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_getYear)]
315                 public static double getYear (object thisObj)
316                 {
317                         return getFullYear (thisObj);
318                 }
319
320                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setDate)]
321                 public static double setDate (object thisObj, double ddate)
322                 {
323                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
324                         DateObject date = (DateObject) thisObj;
325                         double t = DateConstructor.LocalTime (date.ms);
326                         double day = DateConstructor.MakeDay ((double) DateConstructor.YearFromTime (t),
327                                 (double) DateConstructor.MonthFromTime (t), ddate);
328                         double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY));
329                         date.ms = DateConstructor.TimeClip (new_val);
330                         return date.ms;
331                 }
332
333                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setFullYear)]
334                 public static double setFullYear (object thisObj, double dyear,
335                                                   object month, object date)
336                 {
337                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
338                         DateObject dt = (DateObject) thisObj;
339                         double t = DateConstructor.LocalTime (dt.ms);
340                         if (Double.IsNaN (t))
341                                 t = 0;
342
343                         double new_month;
344                         if (month == null)
345                                 new_month = DateConstructor.MonthFromTime (t);
346                         else
347                                 new_month = Convert.ToNumber (month);
348
349                         double new_date;
350                         if (date == null)
351                                 new_date = DateConstructor.DateFromTime (t);
352                         else
353                                 new_date = Convert.ToNumber (date);
354
355                         double day = DateConstructor.MakeDay (dyear, new_month, new_date);
356                         double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY));
357                         dt.ms = DateConstructor.TimeClip (new_val);
358                         return dt.ms;
359                 }
360
361                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setHours)]
362                 public static double setHours (object thisObj, double dhour, object min,
363                                                object sec, object msec)
364                 {
365                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
366                         DateObject date = (DateObject) thisObj;
367                         double t = DateConstructor.LocalTime (date.ms);
368
369                         double new_min;
370                         if (min == null)
371                                 new_min = DateConstructor.MinFromTime (t);
372                         else
373                                 new_min = Convert.ToNumber (min);
374
375                         double new_sec;
376                         if (sec == null)
377                                 new_sec = DateConstructor.SecFromTime (t);
378                         else
379                                 new_sec = Convert.ToNumber (sec);
380
381                         double new_ms;
382                         if (msec == null)
383                                 new_ms = DateConstructor.msFromTime (t);
384                         else
385                                 new_ms = Convert.ToNumber (msec);
386
387                         double time = DateConstructor.MakeTime (dhour, new_min, new_sec, new_ms);
388                         double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
389                         double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, time));
390                         date.ms = DateConstructor.TimeClip (new_val);
391                         return date.ms;
392                 }
393
394                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setMinutes)]
395                 public static double setMinutes (object thisObj, double dmin,
396                                                  object sec, object msec)
397                 {
398                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
399                         DateObject date = (DateObject) thisObj;
400                         double t = DateConstructor.LocalTime (date.ms);
401
402                         double new_sec;
403                         if (sec == null)
404                                 new_sec = DateConstructor.SecFromTime (t);
405                         else
406                                 new_sec = Convert.ToNumber (sec);
407
408                         double new_ms;
409                         if (msec == null)
410                                 new_ms = DateConstructor.msFromTime (t);
411                         else
412                                 new_ms = Convert.ToNumber (msec);
413
414                         double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), dmin, new_sec, new_ms);
415                         double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
416                         double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, time));
417                         date.ms = DateConstructor.TimeClip (new_val);
418                         return date.ms;
419                 }
420
421                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setMilliseconds)]
422                 public static double setMilliseconds (object thisObj, double dmsec)
423                 {
424                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
425                         DateObject date = (DateObject) thisObj;
426                         double t = DateConstructor.LocalTime (date.ms);
427                         double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), DateConstructor.MinFromTime (t),
428                                 DateConstructor.SecFromTime (t), dmsec);
429                         double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
430                         double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, time));
431                         date.ms = DateConstructor.TimeClip (new_val);
432                         return date.ms;
433                 }
434
435                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setMonth)]
436                 public static double setMonth (object thisObj, double dmonth,
437                                                object date)
438                 {
439                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
440                         DateObject dt = (DateObject) thisObj;
441                         double t = DateConstructor.LocalTime (dt.ms);
442
443                         double new_date;
444                         if (date == null)
445                                 new_date = DateConstructor.DateFromTime (t);
446                         else
447                                 new_date = Convert.ToNumber (date);
448                         
449                         double day = DateConstructor.MakeDay ((double) DateConstructor.YearFromTime (t),
450                                 dmonth, new_date);
451                         double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY));
452                         dt.ms = DateConstructor.TimeClip (new_val);
453                         return dt.ms;
454                 }
455
456                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject,
457                         JSBuiltin.Date_setSeconds)]
458                 public static double setSeconds (object thisObj, double dsec, object msec)
459                 {
460                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
461                         DateObject date = (DateObject) thisObj;
462                         double t = DateConstructor.LocalTime (date.ms);
463
464                         double new_ms;
465                         if (msec == null)
466                                 new_ms = DateConstructor.msFromTime (t);
467                         else
468                                 new_ms = Convert.ToNumber (msec);
469
470                         double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), DateConstructor.MinFromTime (t),
471                                 dsec, new_ms);
472                         double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
473                         double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, time));
474                         date.ms = DateConstructor.TimeClip (new_val);
475                         return date.ms;
476                 }
477
478                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setTime)]
479                 public static double setTime (object thisObj, double time)
480                 {
481                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
482                         DateObject date = (DateObject) thisObj;
483                         date.ms = DateConstructor.TimeClip (time);
484                         return date.ms;
485                 }
486
487                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCDate)]
488                 public static double setUTCDate (object thisObj, double ddate)
489                 {
490                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
491                         DateObject date = (DateObject) thisObj;
492                         double t = date.ms;
493                         double day = DateConstructor.MakeDay ((double) DateConstructor.YearFromTime (t),
494                                 (double) DateConstructor.MonthFromTime (t), ddate);
495                         double new_val = DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY);
496                         date.ms = DateConstructor.TimeClip (new_val);
497                         return date.ms;
498                 }
499
500                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCFullYear)]
501                 public static double setUTCFullYear (object thisObj, double dyear,      
502                                                      object month, object date)
503                 {
504                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
505                         DateObject dt = (DateObject) thisObj;
506                         double t = dt.ms;
507                         if (Double.IsNaN (t))
508                                 t = 0;
509
510                         double new_month;
511                         if (month == null)
512                                 new_month = DateConstructor.MonthFromTime (t);
513                         else
514                                 new_month = Convert.ToNumber (month);
515
516                         double new_date;
517                         if (date == null)
518                                 new_date = DateConstructor.DateFromTime (t);
519                         else
520                                 new_date = Convert.ToNumber (date);
521
522                         double day = DateConstructor.MakeDay (dyear, new_month, new_date);
523                         double new_val = DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY);
524                         dt.ms = DateConstructor.TimeClip (new_val);
525                         return dt.ms;
526                 }
527
528                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCHours)]
529                 public static double setUTCHours (object thisObj, double dhour,
530                                                   object min, object sec, object msec)
531                 {
532                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
533                         DateObject date = (DateObject) thisObj;
534                         double t = date.ms;
535
536                         double new_min;
537                         if (min == null)
538                                 new_min = DateConstructor.MinFromTime (t);
539                         else
540                                 new_min = Convert.ToNumber (min);
541
542                         double new_sec;
543                         if (sec == null)
544                                 new_sec = DateConstructor.SecFromTime (t);
545                         else
546                                 new_sec = Convert.ToNumber (sec);
547
548                         double new_ms;
549                         if (msec == null)
550                                 new_ms = DateConstructor.msFromTime (t);
551                         else
552                                 new_ms = Convert.ToNumber (msec);
553
554                         double time = DateConstructor.MakeTime (dhour, new_min, new_sec, new_ms);
555                         double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
556                         double new_val = DateConstructor.MakeDate (day, time);
557                         date.ms = DateConstructor.TimeClip (new_val);
558                         return date.ms;
559                 }
560
561                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCMinutes)]
562                 public static double setUTCMinutes (object thisObj, double dmin,
563                                                     object sec, object msec)
564                 {
565                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
566                         DateObject date = (DateObject) thisObj;
567                         double t = date.ms;
568
569                         double new_sec;
570                         if (sec == null)
571                                 new_sec = DateConstructor.SecFromTime (t);
572                         else
573                                 new_sec = Convert.ToNumber (sec);
574
575                         double new_ms;
576                         if (msec == null)
577                                 new_ms = DateConstructor.msFromTime (t);
578                         else
579                                 new_ms = Convert.ToNumber (msec);
580
581                         double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), dmin, new_sec, new_ms);
582                         double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
583                         double new_val = DateConstructor.MakeDate (day, time);
584                         date.ms = DateConstructor.TimeClip (new_val);
585                         return date.ms;
586                 }
587
588                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCMilliseconds)]
589                 public static double setUTCMilliseconds (object thisObj, double msec)
590                 {
591                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
592                         DateObject date = (DateObject) thisObj;
593                         double t = date.ms;
594                         double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), DateConstructor.MinFromTime (t),
595                                 DateConstructor.SecFromTime (t), msec);
596                         double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
597                         double new_val = DateConstructor.MakeDate (day, time);
598                         date.ms = DateConstructor.TimeClip (new_val);
599                         return date.ms;
600                 }
601
602                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCMonth)]
603                 public static double setUTCMonth (object thisObj, double dmonth, object date)
604                 {
605                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
606                         DateObject dt = (DateObject) thisObj;
607                         double t = dt.ms;
608
609                         double new_date;
610                         if (date == null)
611                                 new_date = DateConstructor.DateFromTime (t);
612                         else
613                                 new_date = Convert.ToNumber (date);
614
615                         double day = DateConstructor.MakeDay ((double) DateConstructor.YearFromTime (t),
616                                 dmonth, new_date);
617                         double new_val = DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY);
618                         dt.ms = DateConstructor.TimeClip (new_val);
619                         return dt.ms;
620                 }
621
622                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCSeconds)]
623                 public static double setUTCSeconds (object thisObj, double dsec, object msec)
624                 {
625                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
626                         DateObject date = (DateObject) thisObj;
627                         double t = date.ms;
628
629                         double new_ms;
630                         if (msec == null)
631                                 new_ms = DateConstructor.msFromTime (t);
632                         else
633                                 new_ms = Convert.ToNumber (msec);
634
635                         double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), DateConstructor.MinFromTime (t),
636                                 dsec, new_ms);
637                         double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
638                         double new_val = DateConstructor.MakeDate (day, time);
639                         date.ms = DateConstructor.TimeClip (new_val);
640                         return date.ms;
641                 }
642
643                 /* Note: See Note for GetYear() for an explanation why we do not emulate obsolete behavior here. */
644                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setYear)]
645                 public static double setYear (object thisObj, double dyear)
646                 {
647                         return setFullYear (thisObj, dyear, null, null);
648                 }
649
650                 internal const string InvalidDateString = "Invalid Date";
651
652                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_toDateString)]
653                 public static string toDateString (object thisObj)
654                 {
655                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
656
657                         DateObject date_obj = (DateObject) thisObj;
658                         double val = date_obj.ms;
659                         double lv = DateConstructor.LocalTime (val);
660                         int year = DateConstructor.YearFromTime (lv);
661                         int month = DateConstructor.MonthFromTime (lv);
662                         int date = DateConstructor.DateFromTime (lv);
663
664                         DateTime dt;
665                         try {
666                                 dt = new DateTime (year, month + 1, date);
667                         } catch (ArgumentOutOfRangeException) {
668                                 return InvalidDateString;
669                         }
670
671                         return dt.ToString ("ddd MMM d yyyy", CultureInfo.InvariantCulture);
672                 }
673
674                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_toGMTString)]
675                 public static string toGMTString (object thisObj)
676                 {
677                         return toUTCString (thisObj);
678                 }
679
680                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_toLocaleDateString)]
681                 public static string toLocaleDateString (object thisObj)
682                 {
683                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
684
685                         DateObject date_obj = (DateObject) thisObj;
686                         double val = date_obj.ms;
687                         double lv = DateConstructor.LocalTime (val);
688                         int year = DateConstructor.YearFromTime (lv);
689                         int month = DateConstructor.MonthFromTime (lv);
690                         int date = DateConstructor.DateFromTime (lv);
691
692                         DateTime dt;
693                         try {
694                                 dt = new DateTime (year, month + 1, date);
695                         } catch (ArgumentOutOfRangeException) {
696                                 return InvalidDateString;
697                         }
698
699                         return dt.ToString ("D");
700                 }
701
702                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_toLocaleString)]
703                 public static string toLocaleString (object thisObj)
704                 {
705                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
706
707                         DateObject date_obj = (DateObject) thisObj;
708                         double val = date_obj.ms;
709                         double lv = DateConstructor.LocalTime (val);
710                         int year = DateConstructor.YearFromTime (lv);
711                         int month = DateConstructor.MonthFromTime (lv);
712                         int date = DateConstructor.DateFromTime (lv);
713                         int hour = DateConstructor.HourFromTime (lv);
714                         int min = DateConstructor.MinFromTime (lv);
715                         int sec = DateConstructor.SecFromTime (lv);
716
717                         DateTime dt;
718                         try {
719                                 dt = new DateTime (year, month + 1, date, hour, min, sec);
720                         } catch (ArgumentOutOfRangeException) {
721                                 return InvalidDateString;
722                         }
723
724                         return dt.ToString ("F");
725                 }
726
727                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_toLocaleTimeString)]
728                 public static string toLocaleTimeString (object thisObj)
729                 {
730                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
731
732                         DateObject date_obj = (DateObject) thisObj;
733                         double val = date_obj.ms;
734                         double lv = DateConstructor.LocalTime (val);
735                         int year = DateConstructor.YearFromTime (lv);
736                         int month = DateConstructor.MonthFromTime (lv);
737                         int date = DateConstructor.DateFromTime (lv);
738                         int hour = DateConstructor.HourFromTime (lv);
739                         int min = DateConstructor.MinFromTime (lv);
740                         int sec = DateConstructor.SecFromTime (lv);
741
742                         DateTime dt;
743                         try {
744                                 dt = new DateTime (year, month + 1, date, hour, min, sec);
745                         } catch (ArgumentOutOfRangeException) {
746                                 return InvalidDateString;
747                         }
748
749                         return dt.ToString ("T");
750                 }
751
752                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_toString)]
753                 public static string toString (object thisObj)
754                 {
755                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
756                         string date_str = toDateString (thisObj);
757                         if (date_str == InvalidDateString)
758                                 return date_str;
759
760                         return date_str.Insert (date_str.LastIndexOf (' '), " " + toTimeString (thisObj));
761                 }
762
763                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_toTimeString)]
764                 public static string toTimeString (object thisObj)
765                 {
766                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
767
768                         DateObject date_obj = (DateObject) thisObj;
769                         double val = date_obj.ms;
770                         double lv = DateConstructor.LocalTime (val);
771                         int hour = DateConstructor.HourFromTime (lv);
772                         int min = DateConstructor.MinFromTime (lv);
773                         int sec = DateConstructor.SecFromTime (lv);
774                         double off = getTimezoneOffset (thisObj);
775
776                         return String.Format (@"{0:00}:{1:00}:{2:00} UTC{3:\+0;\-0;\+0}", hour, min, sec, -off / 60);
777                 }
778
779                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_toUTCString)]
780                 public static string toUTCString (object thisObj)
781                 {
782                         SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
783
784                         DateObject date_obj = (DateObject) thisObj;
785                         double val = date_obj.ms;
786                         int year = DateConstructor.YearFromTime (val);
787                         int month = DateConstructor.MonthFromTime (val);
788                         int date = DateConstructor.DateFromTime (val);
789                         int hour = DateConstructor.HourFromTime (val);
790                         int min = DateConstructor.MinFromTime (val);
791                         int sec = DateConstructor.SecFromTime (val);
792
793                         DateTime dt;
794                         try {
795                                 dt = new DateTime (year, month + 1, date);
796                         } catch (ArgumentOutOfRangeException) {
797                                 return InvalidDateString;
798                         }
799
800                         string date_string = dt.ToString ("ddd, d MMM yyyy ", CultureInfo.InvariantCulture);
801                         string time_string = String.Format (@"{0:00}:{1:00}:{2:00} UTC", hour, min, sec);
802
803                         return date_string + time_string;
804                 }
805
806                 [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_valueOf)]
807                 public static double valueOf (object thisObj)
808                 {
809                         return getTime (thisObj);
810                 }
811         }
812 }