2 * Copyright (C) 2007-2008 Benjamin Otte <otte@gnome.org>
3 * 2007 Pekka Lampila <pekka.lampila@iki.fi>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA
29 #include "swfdec_as_date.h"
30 #include "swfdec_as_context.h"
31 #include "swfdec_as_frame_internal.h"
32 #include "swfdec_as_function.h"
33 #include "swfdec_as_object.h"
34 #include "swfdec_as_strings.h"
35 #include "swfdec_as_internal.h"
36 #include "swfdec_as_native_function.h"
37 #include "swfdec_system.h"
38 #include "swfdec_player_internal.h"
39 #include "swfdec_debug.h"
41 G_DEFINE_TYPE (SwfdecAsDate
, swfdec_as_date
, SWFDEC_TYPE_AS_RELAY
)
48 swfdec_as_date_class_init (SwfdecAsDateClass
*klass
)
53 swfdec_as_date_init (SwfdecAsDate
*date
)
57 /*** Helper functions ***/
59 /* Kind of replacement for gmtime_r, timegm that works the way Flash works */
61 #define MILLISECONDS_PER_SECOND 1000
62 #define SECONDS_PER_MINUTE 60
63 #define MINUTES_PER_HOUR 60
64 #define HOURS_PER_DAY 24
65 #define MONTHS_PER_YEAR 12
67 #define MILLISECONDS_PER_MINUTE 60000
68 #define MILLISECONDS_PER_HOUR 3600000
69 #define MILLISECONDS_PER_DAY 86400000
71 static const int month_offsets
[2][13] = {
72 // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Total
73 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
74 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
90 swfdec_as_date_days_in_year (int year
)
94 } else if (year
% 100) {
96 } else if (year
% 400) {
103 #define IS_LEAP(year) (swfdec_as_date_days_in_year ((year)) == 366)
106 swfdec_as_date_days_since_utc_for_year (double year
)
109 365 * (year
- 1970) +
110 floor (((year
- 1969) / 4.0f
)) -
111 floor (((year
- 1901) / 100.0f
)) +
112 floor (((year
- 1601) / 400.0f
))
117 swfdec_as_date_days_from_utc_to_year (double days
)
119 double low
, high
, pivot
;
121 low
= floor ((days
>= 0 ? days
/ 366.0 : days
/ 365.0)) + 1970;
122 high
= ceil ((days
>= 0 ? days
/ 365.0 : days
/ 366.0)) + 1970;
125 pivot
= floor ((low
+ high
) / 2.0);
127 if (swfdec_as_date_days_since_utc_for_year (pivot
) <= days
) {
128 if (swfdec_as_date_days_since_utc_for_year (pivot
+ 1) > days
) {
142 swfdec_as_date_milliseconds_to_brokentime (double milliseconds
,
143 BrokenTime
*brokentime
)
148 g_assert (brokentime
!= NULL
);
150 /* special case: hours are calculated from different value */
151 if (isfinite (milliseconds
)) {
152 remaining
= floor (milliseconds
+ 0.5);
157 remaining
= floor (remaining
/ MILLISECONDS_PER_HOUR
);
158 brokentime
->hours
= fmod (remaining
, HOURS_PER_DAY
);
160 /* hours done, on with the rest */
161 if (isfinite (milliseconds
)) {
162 remaining
= milliseconds
;
167 brokentime
->milliseconds
= fmod (remaining
, MILLISECONDS_PER_SECOND
);
168 remaining
= floor (remaining
/ MILLISECONDS_PER_SECOND
);
170 brokentime
->seconds
= fmod (remaining
, SECONDS_PER_MINUTE
);
171 remaining
= floor (remaining
/ SECONDS_PER_MINUTE
);
173 brokentime
->minutes
= fmod (remaining
, MINUTES_PER_HOUR
);
174 remaining
= floor (remaining
/ MINUTES_PER_HOUR
);
175 remaining
= floor (remaining
/ HOURS_PER_DAY
);
177 if (milliseconds
< 0) {
178 if (brokentime
->milliseconds
< 0)
179 brokentime
->milliseconds
+= MILLISECONDS_PER_SECOND
;
180 if (brokentime
->seconds
< 0)
181 brokentime
->seconds
+= SECONDS_PER_MINUTE
;
182 if (brokentime
->minutes
< 0)
183 brokentime
->minutes
+= MINUTES_PER_HOUR
;
184 if (brokentime
->hours
< 0)
185 brokentime
->hours
+= HOURS_PER_DAY
;
188 // now remaining == days since 1970
190 if (isfinite (milliseconds
)) {
191 brokentime
->day_of_week
= fmod ((remaining
+ 4), 7);
192 if (brokentime
->day_of_week
< 0)
193 brokentime
->day_of_week
+= 7;
196 brokentime
->day_of_week
= 0;
199 year
= swfdec_as_date_days_from_utc_to_year (remaining
);
200 brokentime
->year
= year
- 1900;
202 remaining
-= swfdec_as_date_days_since_utc_for_year (year
);
203 g_assert (remaining
>= 0 && remaining
<= 365);
205 brokentime
->month
= 0;
206 while (month_offsets
[IS_LEAP (year
)][brokentime
->month
+ 1] <= remaining
)
209 brokentime
->day_of_month
=
210 remaining
- month_offsets
[IS_LEAP (year
)][brokentime
->month
] + 1;
214 swfdec_as_date_brokentime_to_milliseconds (const BrokenTime
*brokentime
)
219 year
= 1900 + brokentime
->year
;
221 milliseconds
= brokentime
->milliseconds
;
222 milliseconds
+= brokentime
->seconds
* MILLISECONDS_PER_SECOND
;
223 milliseconds
+= brokentime
->minutes
* MILLISECONDS_PER_MINUTE
;
224 milliseconds
+= brokentime
->hours
* MILLISECONDS_PER_HOUR
;
225 milliseconds
+= (double)(brokentime
->day_of_month
- 1) * MILLISECONDS_PER_DAY
;
228 swfdec_as_date_days_since_utc_for_year (year
) * MILLISECONDS_PER_DAY
;
230 for (month
= brokentime
->month
; month
< 0; month
+= MONTHS_PER_YEAR
) {
232 (double)month_offsets
[IS_LEAP (--year
)][MONTHS_PER_YEAR
] * MILLISECONDS_PER_DAY
;
235 for (month
= month
; month
>= MONTHS_PER_YEAR
; month
-= MONTHS_PER_YEAR
) {
237 (double)month_offsets
[IS_LEAP (year
++)][MONTHS_PER_YEAR
] * MILLISECONDS_PER_DAY
;
240 milliseconds
+= (double)month_offsets
[IS_LEAP (year
)][month
] * MILLISECONDS_PER_DAY
;
245 /* Wrappers for swfdec_as_value_to_number because we need both double and int
246 * often, and need to generate the right valueOf etc. */
248 // returns TRUE if d is not Infinite or NAN
250 swfdec_as_date_value_to_number_and_integer_floor (SwfdecAsContext
*context
,
251 const SwfdecAsValue
*value
, double *d
, int *num
)
253 *d
= swfdec_as_value_to_number (context
, *value
);
254 if (!isfinite (*d
)) {
263 // returns TRUE if d is not Infinite or NAN
265 swfdec_as_date_value_to_number_and_integer (SwfdecAsContext
*context
,
266 const SwfdecAsValue
*value
, double *d
, int *num
)
268 g_assert (d
!= NULL
);
269 g_assert (num
!= NULL
);
271 // undefined == NAN here, even in version < 7
272 if (SWFDEC_AS_VALUE_IS_UNDEFINED (*value
)) {
275 *d
= swfdec_as_value_to_number (context
, *value
);
277 if (!isfinite (*d
)) {
283 *num
= - (guint
) fmod (-*d
, 4294967296);
285 *num
= (guint
) fmod (*d
, 4294967296);
290 /* The functions to query/modify the current time */
292 // returns TRUE with Infinite and -Infinite, because those values should be
293 // handles like 0 that is returned by below functions
295 swfdec_as_date_is_valid (const SwfdecAsDate
*date
)
297 return !isnan (date
->milliseconds
);
301 swfdec_as_date_set_invalid (SwfdecAsDate
*date
)
303 date
->milliseconds
= NAN
;
307 swfdec_as_date_get_milliseconds_utc (const SwfdecAsDate
*date
)
309 g_assert (swfdec_as_date_is_valid (date
));
311 if (isfinite (date
->milliseconds
)) {
312 return date
->milliseconds
;
319 swfdec_as_date_set_milliseconds_utc (SwfdecAsDate
*date
, double milliseconds
)
321 date
->milliseconds
= milliseconds
;
325 swfdec_as_date_get_milliseconds_local (const SwfdecAsDate *date)
327 g_assert (swfdec_as_date_is_valid (date));
329 if (isfinite (date->milliseconds)) {
330 return date->milliseconds + (double) date->utc_offset * 60 * 1000;
337 swfdec_as_date_set_milliseconds_local (SwfdecAsDate
*date
, double milliseconds
)
340 milliseconds
- (double) date
->utc_offset
* 60 * 1000;
344 swfdec_as_date_get_brokentime_utc (const SwfdecAsDate
*date
,
345 BrokenTime
*brokentime
)
347 g_assert (swfdec_as_date_is_valid (date
));
349 swfdec_as_date_milliseconds_to_brokentime (date
->milliseconds
, brokentime
);
353 swfdec_as_date_set_brokentime_utc (SwfdecAsDate
*date
, BrokenTime
*brokentime
)
355 date
->milliseconds
= swfdec_as_date_brokentime_to_milliseconds (brokentime
);
359 swfdec_as_date_get_brokentime_local (const SwfdecAsDate
*date
,
360 BrokenTime
*brokentime
)
362 g_assert (swfdec_as_date_is_valid (date
));
364 swfdec_as_date_milliseconds_to_brokentime (
365 date
->milliseconds
+ date
->utc_offset
* 60 * 1000, brokentime
);
369 swfdec_as_date_set_brokentime_local (SwfdecAsDate
*date
, BrokenTime
*brokentime
)
371 date
->milliseconds
= swfdec_as_date_brokentime_to_milliseconds (brokentime
) -
372 date
->utc_offset
* 60 * 1000;
375 /* set and get function helpers */
389 static int field_offsets
[] = {
390 G_STRUCT_OFFSET (BrokenTime
, milliseconds
),
391 G_STRUCT_OFFSET (BrokenTime
, seconds
),
392 G_STRUCT_OFFSET (BrokenTime
, minutes
),
393 G_STRUCT_OFFSET (BrokenTime
, hours
),
394 G_STRUCT_OFFSET (BrokenTime
, day_of_week
),
395 G_STRUCT_OFFSET (BrokenTime
, day_of_month
),
396 G_STRUCT_OFFSET (BrokenTime
, month
),
397 G_STRUCT_OFFSET (BrokenTime
, year
),
398 G_STRUCT_OFFSET (BrokenTime
, year
)
402 swfdec_as_date_get_brokentime_value (SwfdecAsDate
*date
, gboolean utc
,
405 BrokenTime brokentime
;
408 swfdec_as_date_get_brokentime_utc (date
, &brokentime
);
410 swfdec_as_date_get_brokentime_local (date
, &brokentime
);
413 return G_STRUCT_MEMBER (int, &brokentime
, field_offset
);
417 swfdec_as_date_set_brokentime_value (SwfdecAsDate
*date
, gboolean utc
,
418 int field_offset
, SwfdecAsContext
*cx
, int number
)
420 BrokenTime brokentime
;
423 swfdec_as_date_get_brokentime_utc (date
, &brokentime
);
425 swfdec_as_date_get_brokentime_local (date
, &brokentime
);
428 G_STRUCT_MEMBER (int, &brokentime
, field_offset
) = number
;
431 swfdec_as_date_set_brokentime_utc (date
, &brokentime
);
433 swfdec_as_date_set_brokentime_local (date
, &brokentime
);
438 swfdec_as_date_set_field (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
439 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
, field_t field
,
444 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_DATE
, &date
, "");
446 if (!swfdec_as_date_is_valid (date
))
447 swfdec_as_value_to_number (cx
, argv
[0]); // calls valueOf
449 if (swfdec_as_date_is_valid (date
) && argc
> 0)
457 swfdec_as_date_value_to_number_and_integer (cx
, &argv
[0], &d
, &number
);
463 swfdec_as_date_set_brokentime_value (date
, utc
,
464 field_offsets
[FIELD_YEAR
], cx
, 0 - 1900);
466 swfdec_as_date_set_brokentime_value (date
, utc
, field_offsets
[field
],
472 // NOTE: Test against double, not the integer
473 if (d
>= 0 && d
< 100)
476 case FIELD_FULL_YEAR
:
479 swfdec_as_date_set_brokentime_value (date
, utc
, field_offsets
[field
],
484 case FIELD_MILLISECONDS
:
488 case FIELD_WEEK_DAYS
:
489 case FIELD_MONTH_DAYS
:
491 swfdec_as_date_set_invalid (date
);
496 g_assert_not_reached ();
500 swfdec_as_date_set_brokentime_value (date
, utc
, field_offsets
[field
], cx
,
504 if (swfdec_as_date_is_valid (date
)) {
505 milliseconds
= swfdec_as_date_get_milliseconds_utc (date
);
506 if (milliseconds
< -8.64e15
|| milliseconds
> 8.64e15
)
507 swfdec_as_date_set_invalid (date
);
511 *ret
= swfdec_as_value_from_number (cx
, date
->milliseconds
);
515 swfdec_as_date_get_field (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
516 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
, field_t field
,
522 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_DATE
, &date
, "");
524 if (!swfdec_as_date_is_valid (date
)) {
525 *ret
= swfdec_as_value_from_number (cx
, NAN
);
529 number
= swfdec_as_date_get_brokentime_value (date
, utc
,
530 field_offsets
[field
]);
532 if (field
== FIELD_FULL_YEAR
)
535 *ret
= swfdec_as_value_from_integer (cx
, number
);
540 SWFDEC_AS_NATIVE (103, 19, swfdec_as_date_toString
)
542 swfdec_as_date_toString (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
543 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
545 static const char *weekday_names
[] =
546 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
547 static const char *month_names
[] =
548 { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
549 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
551 BrokenTime brokentime
;
554 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_DATE
, &date
, "");
556 if (!swfdec_as_date_is_valid (date
)) {
557 SWFDEC_AS_VALUE_SET_STRING (ret
, SWFDEC_AS_STR_Invalid_Date
);
561 swfdec_as_date_get_brokentime_local (date
, &brokentime
);
563 result
= g_strdup_printf ("%s %s %i %02i:%02i:%02i GMT%+03i%02i %i",
564 weekday_names
[brokentime
.day_of_week
% 7],
565 month_names
[brokentime
.month
% 12],
566 brokentime
.day_of_month
,
567 brokentime
.hours
, brokentime
.minutes
, brokentime
.seconds
,
568 date
->utc_offset
/ 60, ABS (date
->utc_offset
% 60),
569 1900 + brokentime
.year
);
571 SWFDEC_AS_VALUE_SET_STRING (ret
, swfdec_as_context_give_string (cx
, result
));
574 SWFDEC_AS_NATIVE (103, 16, swfdec_as_date_getTime
)
576 swfdec_as_date_getTime (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
577 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
581 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_DATE
, &date
, "");
583 *ret
= swfdec_as_value_from_number (cx
, date
->milliseconds
);
586 SWFDEC_AS_NATIVE (103, 18, swfdec_as_date_getTimezoneOffset
)
588 swfdec_as_date_getTimezoneOffset (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
589 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
593 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_DATE
, &date
, "");
595 // reverse of utc_offset
596 *ret
= swfdec_as_value_from_number (cx
, -(date
->utc_offset
));
601 SWFDEC_AS_NATIVE (103, 8, swfdec_as_date_getMilliseconds
)
603 swfdec_as_date_getMilliseconds (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
604 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
606 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_MILLISECONDS
,
610 SWFDEC_AS_NATIVE (103, 128 + 8, swfdec_as_date_getUTCMilliseconds
)
612 swfdec_as_date_getUTCMilliseconds (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
613 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
615 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_MILLISECONDS
,
619 SWFDEC_AS_NATIVE (103, 7, swfdec_as_date_getSeconds
)
621 swfdec_as_date_getSeconds (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
622 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
624 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_SECONDS
, FALSE
);
627 SWFDEC_AS_NATIVE (103, 128 + 7, swfdec_as_date_getUTCSeconds
)
629 swfdec_as_date_getUTCSeconds (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
630 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
632 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_SECONDS
, TRUE
);
635 SWFDEC_AS_NATIVE (103, 6, swfdec_as_date_getMinutes
)
637 swfdec_as_date_getMinutes (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
638 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
640 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_MINUTES
, FALSE
);
643 SWFDEC_AS_NATIVE (103, 128 + 6, swfdec_as_date_getUTCMinutes
)
645 swfdec_as_date_getUTCMinutes (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
646 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
648 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_MINUTES
, TRUE
);
651 SWFDEC_AS_NATIVE (103, 5, swfdec_as_date_getHours
)
653 swfdec_as_date_getHours (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
654 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
656 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_HOURS
, FALSE
);
659 SWFDEC_AS_NATIVE (103, 128 + 5, swfdec_as_date_getUTCHours
)
661 swfdec_as_date_getUTCHours (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
662 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
664 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_HOURS
, TRUE
);
667 SWFDEC_AS_NATIVE (103, 4, swfdec_as_date_getDay
)
669 swfdec_as_date_getDay (SwfdecAsContext
*cx
, SwfdecAsObject
*object
, guint argc
,
670 SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
672 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_WEEK_DAYS
,
676 SWFDEC_AS_NATIVE (103, 128 + 4, swfdec_as_date_getUTCDay
)
678 swfdec_as_date_getUTCDay (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
679 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
681 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_WEEK_DAYS
,
685 SWFDEC_AS_NATIVE (103, 3, swfdec_as_date_getDate
)
687 swfdec_as_date_getDate (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
688 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
690 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_MONTH_DAYS
,
694 SWFDEC_AS_NATIVE (103, 128 + 3, swfdec_as_date_getUTCDate
)
696 swfdec_as_date_getUTCDate (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
697 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
699 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_MONTH_DAYS
,
703 SWFDEC_AS_NATIVE (103, 2, swfdec_as_date_getMonth
)
705 swfdec_as_date_getMonth (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
706 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
708 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_MONTHS
, FALSE
);
711 SWFDEC_AS_NATIVE (103, 128 + 2, swfdec_as_date_getUTCMonth
)
713 swfdec_as_date_getUTCMonth (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
714 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
716 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_MONTHS
, TRUE
);
719 SWFDEC_AS_NATIVE (103, 1, swfdec_as_date_getYear
)
721 swfdec_as_date_getYear (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
722 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
724 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_YEAR
, FALSE
);
727 SWFDEC_AS_NATIVE (103, 128 + 1, swfdec_as_date_getUTCYear
)
729 swfdec_as_date_getUTCYear (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
730 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
732 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_YEAR
, TRUE
);
735 SWFDEC_AS_NATIVE (103, 0, swfdec_as_date_getFullYear
)
737 swfdec_as_date_getFullYear (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
738 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
740 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_FULL_YEAR
,
744 SWFDEC_AS_NATIVE (103, 128 + 0, swfdec_as_date_getUTCFullYear
)
746 swfdec_as_date_getUTCFullYear (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
747 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
749 swfdec_as_date_get_field (cx
, object
, argc
, argv
, ret
, FIELD_FULL_YEAR
,
755 SWFDEC_AS_NATIVE (103, 17, swfdec_as_date_setTime
)
757 swfdec_as_date_setTime (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
758 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
763 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_DATE
, &date
, "");
766 (cx
->version
> 6 || !SWFDEC_AS_VALUE_IS_UNDEFINED (argv
[0]))) {
767 d
= swfdec_as_value_to_number (cx
, argv
[0]);
772 swfdec_as_date_set_milliseconds_utc (date
, trunc (d
));
774 swfdec_as_date_set_milliseconds_utc (date
, NAN
);
777 *ret
= swfdec_as_value_from_number (cx
, date
->milliseconds
);
780 SWFDEC_AS_NATIVE (103, 15, swfdec_as_date_setMilliseconds
)
782 swfdec_as_date_setMilliseconds (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
783 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
785 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_MILLISECONDS
,
789 SWFDEC_AS_NATIVE (103, 128 + 15, swfdec_as_date_setUTCMilliseconds
)
791 swfdec_as_date_setUTCMilliseconds (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
792 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
794 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_MILLISECONDS
,
798 SWFDEC_AS_NATIVE (103, 14, swfdec_as_date_setSeconds
)
800 swfdec_as_date_setSeconds (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
801 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
803 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_SECONDS
, FALSE
);
806 swfdec_as_date_setMilliseconds (cx
, object
, argc
- 1, argv
+ 1, ret
);
809 SWFDEC_AS_NATIVE (103, 128 + 14, swfdec_as_date_setUTCSeconds
)
811 swfdec_as_date_setUTCSeconds (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
812 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
814 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_SECONDS
, TRUE
);
817 swfdec_as_date_setUTCMilliseconds (cx
, object
, argc
- 1, argv
+ 1, ret
);
820 SWFDEC_AS_NATIVE (103, 13, swfdec_as_date_setMinutes
)
822 swfdec_as_date_setMinutes (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
823 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
825 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_MINUTES
, FALSE
);
828 swfdec_as_date_setSeconds (cx
, object
, argc
- 1, argv
+ 1, ret
);
831 SWFDEC_AS_NATIVE (103, 128 + 13, swfdec_as_date_setUTCMinutes
)
833 swfdec_as_date_setUTCMinutes (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
834 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
836 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_MINUTES
, TRUE
);
839 swfdec_as_date_setUTCSeconds (cx
, object
, argc
- 1, argv
+ 1, ret
);
842 SWFDEC_AS_NATIVE (103, 12, swfdec_as_date_setHours
)
844 swfdec_as_date_setHours (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
845 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
847 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_HOURS
, FALSE
);
850 swfdec_as_date_setMinutes (cx
, object
, argc
- 1, argv
+ 1, ret
);
853 SWFDEC_AS_NATIVE (103, 128 + 12, swfdec_as_date_setUTCHours
)
855 swfdec_as_date_setUTCHours (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
856 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
858 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_HOURS
, TRUE
);
861 swfdec_as_date_setUTCMinutes (cx
, object
, argc
- 1, argv
+ 1, ret
);
864 SWFDEC_AS_NATIVE (103, 11, swfdec_as_date_setDate
)
866 swfdec_as_date_setDate (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
867 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
869 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_MONTH_DAYS
,
873 SWFDEC_AS_NATIVE (103, 128 + 11, swfdec_as_date_setUTCDate
)
875 swfdec_as_date_setUTCDate (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
876 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
878 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_MONTH_DAYS
,
882 SWFDEC_AS_NATIVE (103, 10, swfdec_as_date_setMonth
)
884 swfdec_as_date_setMonth (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
885 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
887 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_MONTHS
, FALSE
);
890 swfdec_as_date_setDate (cx
, object
, argc
- 1, argv
+ 1, ret
);
893 SWFDEC_AS_NATIVE (103, 128 + 10, swfdec_as_date_setUTCMonth
)
895 swfdec_as_date_setUTCMonth (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
896 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
898 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_MONTHS
, TRUE
);
901 swfdec_as_date_setUTCDate (cx
, object
, argc
- 1, argv
+ 1, ret
);
904 SWFDEC_AS_NATIVE (103, 20, swfdec_as_date_setYear
)
906 swfdec_as_date_setYear (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
907 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
909 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_YEAR
, FALSE
);
912 swfdec_as_date_setMonth (cx
, object
, argc
- 1, argv
+ 1, ret
);
915 SWFDEC_AS_NATIVE (103, 9, swfdec_as_date_setFullYear
)
917 swfdec_as_date_setFullYear (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
918 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
920 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_FULL_YEAR
,
924 swfdec_as_date_setMonth (cx
, object
, argc
- 1, argv
+ 1, ret
);
927 SWFDEC_AS_NATIVE (103, 128 + 9, swfdec_as_date_setUTCFullYear
)
929 swfdec_as_date_setUTCFullYear (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
930 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
932 swfdec_as_date_set_field (cx
, object
, argc
, argv
, ret
, FIELD_FULL_YEAR
,
936 swfdec_as_date_setUTCMonth (cx
, object
, argc
- 1, argv
+ 1, ret
);
941 SWFDEC_AS_NATIVE (103, 257, swfdec_as_date_UTC
)
943 swfdec_as_date_UTC (SwfdecAsContext
*cx
, SwfdecAsObject
*object
, guint argc
,
944 SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
949 BrokenTime brokentime
;
951 // special case: ignore undefined and everything after it
952 for (i
= 0; i
< argc
; i
++) {
953 if (SWFDEC_AS_VALUE_IS_UNDEFINED (argv
[i
])) {
959 memset (&brokentime
, 0, sizeof (brokentime
));
962 if (swfdec_as_date_value_to_number_and_integer_floor (cx
, &argv
[0], &d
,
966 // special case: if year is not finite set it to -1900
973 // if we don't got atleast two values, return undefined
974 // do it only here, so valueOf first arg is called
978 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[1], &d
,
980 brokentime
.month
= num
;
982 // special case: if month is not finite set year to -1900
984 brokentime
.month
= 0;
988 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[2], &d
,
990 brokentime
.day_of_month
= num
;
992 *ret
= swfdec_as_value_from_number (cx
, d
);
996 brokentime
.day_of_month
= 1;
1000 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[3], &d
,
1002 brokentime
.hours
= num
;
1004 *ret
= swfdec_as_value_from_number (cx
, d
);
1010 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[4], &d
,
1012 brokentime
.minutes
= num
;
1014 *ret
= swfdec_as_value_from_number (cx
, d
);
1020 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[5], &d
,
1022 brokentime
.seconds
= num
;
1024 *ret
= swfdec_as_value_from_number (cx
, d
);
1030 brokentime
.year
= year
- 1900;
1032 brokentime
.year
= year
;
1036 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[6], &d
,
1038 brokentime
.milliseconds
= num
;
1040 *ret
= swfdec_as_value_from_number (cx
, d
);
1045 *ret
= swfdec_as_value_from_number (cx
,
1046 swfdec_as_date_brokentime_to_milliseconds (&brokentime
));
1051 SWFDEC_AS_NATIVE (103, 256, swfdec_as_date_construct
)
1053 swfdec_as_date_construct (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
1054 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
1059 if (!swfdec_as_context_is_constructing (cx
)) {
1060 object
= swfdec_as_object_new_empty (cx
);
1061 swfdec_as_object_set_constructor_by_name (object
, SWFDEC_AS_STR_Date
, NULL
);
1064 date
= g_object_new (SWFDEC_TYPE_AS_DATE
, "context", cx
, NULL
);
1065 swfdec_as_object_set_relay (object
, SWFDEC_AS_RELAY (date
));
1067 /* FIXME: find a general solution here */
1068 if (SWFDEC_IS_PLAYER (swfdec_gc_object_get_context (date
))) {
1070 SWFDEC_PLAYER (swfdec_gc_object_get_context (date
))->priv
->system
->utc_offset
;
1073 // don't accept arguments when not constructing
1074 if (!cx
->frame
->construct
)
1077 // special case: ignore undefined and everything after it
1078 for (i
= 0; i
< argc
; i
++) {
1079 if (SWFDEC_AS_VALUE_IS_UNDEFINED (argv
[i
])) {
1085 if (argc
== 0) // current time, local
1089 swfdec_as_context_get_time (cx
, &tv
);
1090 /* Use millisecond granularity here. Otherwise the value returned by
1091 * getTime() or toString() has a decimal point which breaks Flash files.
1093 swfdec_as_date_set_milliseconds_utc (date
,
1094 tv
.tv_sec
* 1000.0 + tv
.tv_usec
/ 1000);
1096 else if (argc
== 1) // milliseconds from epoch, local
1098 // need to save directly to keep fractions of a milliseconds
1099 date
->milliseconds
= swfdec_as_value_to_number (cx
, argv
[0]);
1101 else // year, month etc. local
1105 BrokenTime brokentime
;
1107 date
->milliseconds
= 0;
1109 memset (&brokentime
, 0, sizeof (brokentime
));
1114 if (swfdec_as_date_value_to_number_and_integer_floor (cx
, &argv
[i
++], &d
,
1118 // special case: if year is not finite set it to -1900
1126 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[i
++], &d
,
1128 brokentime
.month
= num
;
1130 // special case: if month is not finite set year to -1900
1132 brokentime
.month
= 0;
1137 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[i
++], &d
,
1139 brokentime
.day_of_month
= num
;
1141 date
->milliseconds
+= d
;
1144 brokentime
.day_of_month
= 1;
1148 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[i
++], &d
,
1150 brokentime
.hours
= num
;
1152 date
->milliseconds
+= d
;
1157 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[i
++], &d
,
1159 brokentime
.minutes
= num
;
1161 date
->milliseconds
+= d
;
1166 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[i
++], &d
,
1168 brokentime
.seconds
= num
;
1170 date
->milliseconds
+= d
;
1175 brokentime
.year
= year
- 1900;
1177 brokentime
.year
= year
;
1181 if (swfdec_as_date_value_to_number_and_integer (cx
, &argv
[i
++], &d
,
1183 brokentime
.milliseconds
+= num
;
1185 date
->milliseconds
+= d
;
1189 if (date
->milliseconds
== 0) {
1190 swfdec_as_date_set_milliseconds_local (date
,
1191 swfdec_as_date_brokentime_to_milliseconds (&brokentime
));
1195 SWFDEC_AS_VALUE_SET_OBJECT (ret
, object
);