Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Redistribution and use in source and binary forms, with or without
3 : // modification, are permitted provided that the following conditions are
4 : // met:
5 : //
6 : // * Redistributions of source code must retain the above copyright
7 : // notice, this list of conditions and the following disclaimer.
8 : // * Redistributions in binary form must reproduce the above
9 : // copyright notice, this list of conditions and the following
10 : // disclaimer in the documentation and/or other materials provided
11 : // with the distribution.
12 : // * Neither the name of Google Inc. nor the names of its
13 : // contributors may be used to endorse or promote products derived
14 : // from this software without specific prior written permission.
15 : //
16 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 :
28 : #include "src/date.h"
29 : #include "src/global-handles.h"
30 : #include "src/isolate.h"
31 : #include "src/v8.h"
32 : #include "test/cctest/cctest.h"
33 :
34 : namespace v8 {
35 : namespace internal {
36 :
37 10 : class DateCacheMock: public DateCache {
38 : public:
39 : struct Rule {
40 : int year, start_month, start_day, end_month, end_day, offset_sec;
41 : };
42 :
43 : DateCacheMock(int local_offset, Rule* rules, int rules_count)
44 5 : : local_offset_(local_offset), rules_(rules), rules_count_(rules_count) {}
45 :
46 : protected:
47 12030 : int GetDaylightSavingsOffsetFromOS(int64_t time_sec) override {
48 12030 : int days = DaysFromTime(time_sec * 1000);
49 12030 : int time_in_day_sec = TimeInDay(time_sec * 1000, days) / 1000;
50 : int year, month, day;
51 12030 : YearMonthDayFromDays(days, &year, &month, &day);
52 12030 : Rule* rule = FindRuleFor(year, month, day, time_in_day_sec);
53 12030 : return rule == nullptr ? 0 : rule->offset_sec * 1000;
54 : }
55 :
56 12030 : int GetLocalOffsetFromOS(int64_t time_sec, bool is_utc) override {
57 12030 : return local_offset_ + GetDaylightSavingsOffsetFromOS(time_sec);
58 : }
59 :
60 : private:
61 12030 : Rule* FindRuleFor(int year, int month, int day, int time_in_day_sec) {
62 : Rule* result = nullptr;
63 108270 : for (int i = 0; i < rules_count_; i++)
64 48120 : if (Match(&rules_[i], year, month, day, time_in_day_sec)) {
65 8110 : result = &rules_[i];
66 : }
67 12030 : return result;
68 : }
69 :
70 :
71 48120 : bool Match(Rule* rule, int year, int month, int day, int time_in_day_sec) {
72 48120 : if (rule->year != 0 && rule->year != year) return false;
73 12030 : if (rule->start_month > month) return false;
74 10090 : if (rule->end_month < month) return false;
75 9050 : int start_day = ComputeRuleDay(year, rule->start_month, rule->start_day);
76 9050 : if (rule->start_month == month && start_day > day) return false;
77 9860 : if (rule->start_month == month && start_day == day &&
78 910 : 2 * 3600 > time_in_day_sec)
79 : return false;
80 8940 : int end_day = ComputeRuleDay(year, rule->end_month, rule->end_day);
81 8940 : if (rule->end_month == month && end_day < day) return false;
82 8220 : if (rule->end_month == month && end_day == day &&
83 110 : 2 * 3600 <= time_in_day_sec)
84 : return false;
85 8110 : return true;
86 : }
87 :
88 :
89 17990 : int ComputeRuleDay(int year, int month, int day) {
90 17990 : if (day != 0) return day;
91 17990 : int days = DaysFromYearMonth(year, month);
92 : // Find the first Sunday of the month.
93 147060 : while (Weekday(days + day) != 6) day++;
94 17990 : return day + 1;
95 : }
96 :
97 : int local_offset_;
98 : Rule* rules_;
99 : int rules_count_;
100 : };
101 :
102 : static int64_t TimeFromYearMonthDay(DateCache* date_cache,
103 : int year,
104 : int month,
105 : int day) {
106 475 : int64_t result = date_cache->DaysFromYearMonth(year, month);
107 475 : return (result + day - 1) * DateCache::kMsPerDay;
108 : }
109 :
110 :
111 6015 : static void CheckDST(int64_t time) {
112 : Isolate* isolate = CcTest::i_isolate();
113 : DateCache* date_cache = isolate->date_cache();
114 : int64_t actual = date_cache->ToLocal(time);
115 6015 : int64_t expected = time + date_cache->GetLocalOffsetFromOS(time, true);
116 6015 : CHECK_EQ(actual, expected);
117 6015 : }
118 :
119 :
120 26644 : TEST(DaylightSavingsTime) {
121 5 : LocalContext context;
122 5 : v8::Isolate* isolate = context->GetIsolate();
123 10 : v8::HandleScope scope(isolate);
124 : DateCacheMock::Rule rules[] = {
125 : {0, 2, 0, 10, 0, 3600}, // DST from March to November in any year.
126 : {2010, 2, 0, 7, 20, 3600}, // DST from March to August 20 in 2010.
127 : {2010, 7, 20, 8, 10, 0}, // No DST from August 20 to September 10 in 2010.
128 : {2010, 8, 10, 10, 0, 3600}, // DST from September 10 to November in 2010.
129 5 : };
130 :
131 : int local_offset_ms = -36000000; // -10 hours.
132 :
133 : DateCacheMock* date_cache =
134 5 : new DateCacheMock(local_offset_ms, rules, arraysize(rules));
135 :
136 5 : reinterpret_cast<Isolate*>(isolate)->set_date_cache(date_cache);
137 :
138 : int64_t start_of_2010 = TimeFromYearMonthDay(date_cache, 2010, 0, 1);
139 : int64_t start_of_2011 = TimeFromYearMonthDay(date_cache, 2011, 0, 1);
140 : int64_t august_20 = TimeFromYearMonthDay(date_cache, 2010, 7, 20);
141 : int64_t september_10 = TimeFromYearMonthDay(date_cache, 2010, 8, 10);
142 5 : CheckDST((august_20 + september_10) / 2);
143 5 : CheckDST(september_10);
144 5 : CheckDST(september_10 + 2 * 3600);
145 5 : CheckDST(september_10 + 2 * 3600 - 1000);
146 5 : CheckDST(august_20 + 2 * 3600);
147 5 : CheckDST(august_20 + 2 * 3600 - 1000);
148 5 : CheckDST(august_20);
149 : // Check each day of 2010.
150 1835 : for (int64_t time = start_of_2011 + 2 * 3600;
151 1835 : time >= start_of_2010;
152 : time -= DateCache::kMsPerDay) {
153 1830 : CheckDST(time);
154 1830 : CheckDST(time - 1000);
155 1830 : CheckDST(time + 1000);
156 : }
157 : // Check one day from 2010 to 2100.
158 915 : for (int year = 2100; year >= 2010; year--) {
159 455 : CheckDST(TimeFromYearMonthDay(date_cache, year, 5, 5));
160 : }
161 5 : CheckDST((august_20 + september_10) / 2);
162 5 : CheckDST(september_10);
163 5 : CheckDST(september_10 + 2 * 3600);
164 5 : CheckDST(september_10 + 2 * 3600 - 1000);
165 5 : CheckDST(august_20 + 2 * 3600);
166 5 : CheckDST(august_20 + 2 * 3600 - 1000);
167 5 : CheckDST(august_20);
168 5 : }
169 :
170 : namespace {
171 : int legacy_parse_count = 0;
172 10 : void DateParseLegacyCounterCallback(v8::Isolate* isolate,
173 : v8::Isolate::UseCounterFeature feature) {
174 10 : if (feature == v8::Isolate::kLegacyDateParser) legacy_parse_count++;
175 10 : }
176 : } // anonymous namespace
177 :
178 26644 : TEST(DateParseLegacyUseCounter) {
179 5 : CcTest::InitializeVM();
180 10 : v8::HandleScope scope(CcTest::isolate());
181 5 : LocalContext context;
182 5 : CcTest::isolate()->SetUseCounterCallback(DateParseLegacyCounterCallback);
183 5 : CHECK_EQ(0, legacy_parse_count);
184 : CompileRun("Date.parse('2015-02-31')");
185 5 : CHECK_EQ(0, legacy_parse_count);
186 : CompileRun("Date.parse('2015-02-31T11:22:33.444Z01:23')");
187 5 : CHECK_EQ(0, legacy_parse_count);
188 : CompileRun("Date.parse('2015-02-31T11:22:33.444')");
189 5 : CHECK_EQ(0, legacy_parse_count);
190 : CompileRun("Date.parse('2000 01 01')");
191 5 : CHECK_EQ(1, legacy_parse_count);
192 : CompileRun("Date.parse('2015-02-31T11:22:33.444 ')");
193 5 : CHECK_EQ(1, legacy_parse_count);
194 5 : }
195 :
196 : } // namespace internal
197 79917 : } // namespace v8
|