diff --git a/ecmascript/date_parse.cpp b/ecmascript/date_parse.cpp index 2bd7c516b75e1265f861b1eb6e9c515fde54d57d..c3a475071ea408ec293da71ebff9145a957bd6ec 100644 --- a/ecmascript/date_parse.cpp +++ b/ecmascript/date_parse.cpp @@ -170,7 +170,7 @@ bool DateParse::ParseIsoDateTime(DateProxy *proxy, DayValue *dayValue, TimeValue } } } - if (timeZone->IsLocal() && timeValue->GetIndex() == 0) { + if (timeZone->IsLocal() && timeValue->IsEmpty()) { timeZone->SetUTC(); } dayValue->SetIsoFlag(true); @@ -225,6 +225,12 @@ bool DateParse::ParseLegacyDates(DateProxy *proxy, DayValue *dayValue, TimeValue dayValue->SetMonth(date.GetValue()); } else if (date.IsTimeZone() && hasNumber) { timeZone->SetUTC(); + } else if (date.IsAMOrPM()) { + if (!timeValue->IsEmpty()) { + timeValue->FixHourForAMOrPM(date.GetValue()); + } else if (hasNumber) { + return false; + } } else if (date.IsTimeFlag() || date.IsInvalidWord()) { if (hasNumber) { return false; @@ -232,7 +238,7 @@ bool DateParse::ParseLegacyDates(DateProxy *proxy, DayValue *dayValue, TimeValue if (proxy->GetDate().IsNumber()) { return false; } - } else if (date.IsSign() && ((timeValue->GetIndex() > 0) || timeZone->IsUTC())) { + } else if (date.IsSign() && (!timeValue->IsEmpty() || timeZone->IsUTC())) { if (date.IsSymbol('-')) { timeZone->SetSign(-1); } else { @@ -307,7 +313,7 @@ DateParse::DateUnit DateParse::DateProxy::Read() int minLen = len < 3 ? len : 3; CString str(buf, minLen); int value = 0; - DateValueType type = MatchKeyWord(str, &value); + DateValueType type = MatchKeyWord(str, minLen, &value); return DateUnit::Word(type, value, len); } if (str_->IsSpaceOrTab()) { @@ -318,23 +324,34 @@ DateParse::DateUnit DateParse::DateProxy::Read() return DateUnit::Unknown(); } -DateParse::DateValueType DateParse::DateProxy::MatchKeyWord(const CString &str, int *value) +DateParse::DateValueType DateParse::DateProxy::MatchKeyWord(const CString &str, int strLen, int *value) { - if (str == "t") { - return DATE_TIME_FALG; - } - if (str == "z") { - return DATE_TIME_ZONE; - } - - if (str == "utc" || str == "gmt") { - *value = 1; - return DATE_TIME_ZONE; - } - for (int i = 0; i < MOUTH_PER_YEAR; i++) { - if (str == DateParse::MONTH_NAME[i]) { - *value = i + 1; - return DATE_MONTH; + if (strLen == 1) { // 1: length of "t"/"z". + if (str == "t") { + return DATE_TIME_FALG; + } + if (str == "z") { + return DATE_TIME_ZONE; + } + } else if (strLen == 3) { // 3: length of "utc"/"gmt". + if (str == "utc" || str == "gmt") { + *value = 1; + return DATE_TIME_ZONE; + } + for (int i = 0; i < MOUTH_PER_YEAR; i++) { + if (str == DateParse::MONTH_NAME[i]) { + *value = i + 1; + return DATE_MONTH; + } + } + } else if (strLen == 2) { // 2: length of "am"/"pm". + if (str == "am") { + *value = 0; + return DATE_AM_PM; + } + if (str == "pm") { + *value = 12; // 12: while date string includes PM, the hour need to be fixed. + return DATE_AM_PM; } } return DATE_INVALID_WORD; diff --git a/ecmascript/date_parse.h b/ecmascript/date_parse.h index f3ad7c5f62e9451f768eb2d1551e3b4b2a9ecd1a..a8bb037683a567d5f5ade5abdae55af9caa064bb 100644 --- a/ecmascript/date_parse.h +++ b/ecmascript/date_parse.h @@ -158,6 +158,7 @@ private: DATE_TIME_ZONE, DATE_TIME_FALG, DATE_MONTH, + DATE_AM_PM, DATE_INVALID_WORD, DATE_WORD_START = DATE_TIME_ZONE, }; @@ -214,6 +215,11 @@ private: return type_ == DATE_MONTH; } + bool IsAMOrPM() const + { + return type_ == DATE_AM_PM; + } + bool IsWord() const { return type_ >= DATE_TIME_ZONE; @@ -343,7 +349,7 @@ private: } private: DateUnit Read(); - DateValueType MatchKeyWord(const CString &str, int *value); + DateValueType MatchKeyWord(const CString &str, int strLen, int *value); StringReader *str_ {nullptr}; DateUnit date_; @@ -402,6 +408,13 @@ private: return false; } + inline void FixHourForAMOrPM(int value) + { + if (data_[HOUR_IDX] < 12) { // 12: while date string includes PM, the hour need to be fixed. + data_[HOUR_IDX] += value; + } + } + static bool MinuteIsValid(int n) { // 59 : max min @@ -450,9 +463,9 @@ private: return value / divisor; } - int GetIndex() const + inline bool IsEmpty() const { - return index_; + return index_ == HOUR_IDX; } bool IsValid(int n) const @@ -470,6 +483,7 @@ private: bool SetTimeValue(int *time); private: static constexpr int TIME_LEN = 4; + static constexpr int HOUR_IDX = 0; int data_[TIME_LEN] {0}; int index_ {0}; }; diff --git a/test/moduletest/dateparse/dateparse.js b/test/moduletest/dateparse/dateparse.js index a0d6b02984ada3d19314ec4aa84c88015896a7e5..8bf2818a4f3ef3564e1f5d792b6aec25382ee38a 100644 --- a/test/moduletest/dateparse/dateparse.js +++ b/test/moduletest/dateparse/dateparse.js @@ -54,3 +54,20 @@ let d7 = new Date("Wed, 26-Jun-2019 GMT") print(d7.getTime()) let date8=new Date('Jun,19 12:03:45 GMT') print(date8.getTime()) + +let d9 = new Date('06/15/2023 02:30:45 AM') +print(d9) +let d10 = new Date('06/15/2023 15:30:45 AM') +print(d10) +let d11 = new Date('2023-05-20 03:45:30 PM') +print(d11) +let d12 = new Date('2023-05-20 15:45:30 PM') +print(d12) +let d13 = new Date('2023-05-20 PM 03:45:30') +print(d13) +let d14 = new Date('2023-05-20 03:45:PM30') +print(d14) +let d15 = new Date('PM 2023-05-20 03:45:30') +print(d15) +let d16 = new Date('PM2023-05-20 03:45:30') +print(d16) diff --git a/test/moduletest/dateparse/expect_output.txt b/test/moduletest/dateparse/expect_output.txt index 780190602a319dd9dcade5a91f341feef45b8807..ee576de47cdeb24a72a08403bb94ed6c1754a509 100644 --- a/test/moduletest/dateparse/expect_output.txt +++ b/test/moduletest/dateparse/expect_output.txt @@ -32,3 +32,11 @@ true 1561507200000 1561507200000 992952225000 +Thu Jun 15 2023 02:30:45 GMT+0800 +Thu Jun 15 2023 15:30:45 GMT+0800 +Sat May 20 2023 15:45:30 GMT+0800 +Sat May 20 2023 15:45:30 GMT+0800 +Invalid Date +Invalid Date +Sat May 20 2023 03:45:30 GMT+0800 +Sat May 20 2023 03:45:30 GMT+0800