• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/picker/datepicker_pattern.h"
17 
18 #include <stdint.h>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "base/memory/ace_type.h"
24 #include "base/utils/utils.h"
25 #include "core/components/picker/picker_base_component.h"
26 #include "core/components/theme/icon_theme.h"
27 #include "core/components_ng/base/frame_node.h"
28 #include "core/components_ng/event/click_event.h"
29 #include "core/components_ng/pattern/button/button_pattern.h"
30 #include "core/components_ng/pattern/image/image_layout_property.h"
31 #include "core/components_ng/pattern/picker/datepicker_column_pattern.h"
32 #include "core/components_v2/inspector/inspector_constants.h"
33 #include "core/pipeline/pipeline_base.h"
34 #include "core/pipeline_ng/ui_task_scheduler.h"
35 
36 namespace OHOS::Ace::NG {
37 namespace {
38 constexpr int32_t SINGLE_CHILD_SIZE = 1;
39 constexpr int32_t CHILD_SIZE = 3;
40 constexpr uint32_t MIN_MONTH = 1;
41 constexpr uint32_t MAX_MONTH = 12;
42 constexpr uint32_t MIN_DAY = 1;
43 const Dimension PRESS_INTERVAL = 4.0_vp;
44 const Dimension PRESS_RADIUS = 8.0_vp;
45 const int32_t UNOPTION_COUNT = 2;
46 } // namespace
47 bool DatePickerPattern::inited_ = false;
48 const std::string DatePickerPattern::empty_;
49 const PickerDateF DatePickerPattern::emptyPickerDate_;
50 std::unordered_map<uint32_t, std::string> DatePickerPattern::years_;       // year from 1900 to 2100,count is 201
51 std::unordered_map<uint32_t, std::string> DatePickerPattern::solarMonths_; // solar month from 1 to 12,count is 12
52 std::unordered_map<uint32_t, std::string> DatePickerPattern::solarDays_;   // solar day from 1 to 31, count is 31
53 std::unordered_map<uint32_t, std::string> DatePickerPattern::lunarMonths_; // lunar month from 1 to 24, count is 24
54 std::unordered_map<uint32_t, std::string> DatePickerPattern::lunarDays_;   // lunar day from 1 to 30, count is 30
55 std::vector<std::string> DatePickerPattern::tagOrder_;    // order of year month day
56 std::vector<std::string> DatePickerPattern::localizedMonths_;
57 
OnAttachToFrameNode()58 void DatePickerPattern::OnAttachToFrameNode()
59 {
60     auto host = GetHost();
61     CHECK_NULL_VOID(host);
62     host->GetRenderContext()->SetClipToFrame(true);
63     host->GetRenderContext()->UpdateClipEdge(true);
64 }
65 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)66 bool DatePickerPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
67 {
68     CHECK_NULL_RETURN(dirty, false);
69     auto host = GetHost();
70     CHECK_NULL_RETURN(host, false);
71     auto context = host->GetContext();
72     CHECK_NULL_RETURN(context, false);
73     auto pickerTheme = context->GetTheme<PickerTheme>();
74     CHECK_NULL_RETURN(pickerTheme, false);
75     auto children = host->GetChildren();
76     auto heigth = pickerTheme->GetDividerSpacing();
77     for (const auto& child : children) {
78         auto columnNode = DynamicCast<FrameNode>(child->GetLastChild());
79         auto width = columnNode->GetGeometryNode()->GetFrameSize().Width();
80         auto buttonNode = DynamicCast<FrameNode>(child->GetFirstChild());
81         auto buttonConfirmLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
82         buttonConfirmLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT_MAIN_AXIS);
83         buttonConfirmLayoutProperty->UpdateType(ButtonType::NORMAL);
84         buttonConfirmLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(PRESS_RADIUS));
85         buttonConfirmLayoutProperty->UpdateUserDefinedIdealSize(
86             CalcSize(CalcLength(width - PRESS_INTERVAL.ConvertToPx()), CalcLength(heigth - PRESS_INTERVAL)));
87         auto buttonConfirmRenderContext = buttonNode->GetRenderContext();
88         buttonConfirmRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
89         buttonNode->MarkModifyDone();
90     }
91     return true;
92 }
93 
OnModifyDone()94 void DatePickerPattern::OnModifyDone()
95 {
96     if (isFiredDateChange_ && !isForceUpdate_) {
97         isFiredDateChange_ = false;
98         isForceUpdate_ = false;
99         return;
100     }
101 
102     auto host = GetHost();
103     CHECK_NULL_VOID(host);
104     InitDisabled();
105     if (ShowMonthDays()) {
106         FlushMonthDaysColumn();
107     } else {
108         FlushColumn();
109     }
110     ShowTitle(GetTitleId());
111     SetChangeCallback([weak = WeakClaim(this)](const RefPtr<FrameNode>& tag, bool add, uint32_t index, bool notify) {
112         auto refPtr = weak.Upgrade();
113         CHECK_NULL_VOID(refPtr);
114         refPtr->HandleColumnChange(tag, add, index, notify);
115     });
116     SetEventCallback([weak = WeakClaim(this), titleId = GetTitleId()](bool refresh) {
117         auto refPtr = weak.Upgrade();
118         CHECK_NULL_VOID(refPtr);
119         refPtr->FireChangeEvent(refresh);
120         if (refresh) {
121             refPtr->ShowTitle(titleId);
122         }
123     });
124     auto focusHub = host->GetFocusHub();
125     if (focusHub) {
126         InitOnKeyEvent(focusHub);
127     }
128 }
129 
InitDisabled()130 void DatePickerPattern::InitDisabled()
131 {
132     auto host = GetHost();
133     CHECK_NULL_VOID(host);
134     auto eventHub = host->GetEventHub<EventHub>();
135     CHECK_NULL_VOID(eventHub);
136     auto renderContext = host->GetRenderContext();
137     enabled_ = eventHub->IsEnabled();
138     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
139 }
140 
OnLanguageConfigurationUpdate()141 void DatePickerPattern::OnLanguageConfigurationUpdate()
142 {
143     auto buttonConfirmNode = weakButtonConfirm_.Upgrade();
144     CHECK_NULL_VOID(buttonConfirmNode);
145     auto confirmNode = buttonConfirmNode->GetFirstChild();
146     auto confirmNodeLayout = AceType::DynamicCast<FrameNode>(confirmNode)->GetLayoutProperty<TextLayoutProperty>();
147     confirmNodeLayout->UpdateContent(Localization::GetInstance()->GetEntryLetters("common.ok"));
148     confirmNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
149 
150     auto buttonCancelNode = weakButtonCancel_.Upgrade();
151     CHECK_NULL_VOID(buttonCancelNode);
152     auto cancelNode = buttonCancelNode->GetFirstChild();
153     auto cancelNodeLayout = AceType::DynamicCast<FrameNode>(cancelNode)->GetLayoutProperty<TextLayoutProperty>();
154     cancelNodeLayout->UpdateContent(Localization::GetInstance()->GetEntryLetters("common.cancel"));
155     cancelNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
156 }
157 
HandleColumnChange(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,bool needNotify)158 void DatePickerPattern::HandleColumnChange(const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, bool needNotify)
159 {
160     CHECK_NULL_VOID(GetHost());
161     std::vector<RefPtr<FrameNode>> tags;
162     if (ShowMonthDays()) {
163         HandleMonthDaysChange(tag, isAdd, index, tags);
164     } else {
165         OnDataLinking(tag, isAdd, index, tags);
166     }
167     for (const auto& tag : tags) {
168         auto iter = std::find_if(datePickerColumns_.begin(), datePickerColumns_.end(), [&tag](const auto& c) {
169             auto column = c.Upgrade();
170             return column && column->GetId() == tag->GetId();
171         });
172         if (iter != datePickerColumns_.end()) {
173             auto datePickerColumn = (*iter).Upgrade();
174             CHECK_NULL_VOID(datePickerColumn);
175             auto datePickerColumnPattern = datePickerColumn->GetPattern<DatePickerColumnPattern>();
176             CHECK_NULL_VOID(datePickerColumnPattern);
177             datePickerColumnPattern->FlushCurrentOptions(isAdd, true, false);
178         }
179     }
180 }
181 
SetEventCallback(EventCallback && value)182 void DatePickerPattern::SetEventCallback(EventCallback&& value)
183 {
184     auto host = GetHost();
185     CHECK_NULL_VOID(host);
186     auto children = host->GetChildren();
187     for (const auto& child : children) {
188         auto stackNode = DynamicCast<FrameNode>(child);
189         CHECK_NULL_VOID(stackNode);
190         auto childNode = stackNode->GetChildAtIndex(1);
191         CHECK_NULL_VOID(childNode);
192         auto datePickerColumnPattern = DynamicCast<FrameNode>(childNode)->GetPattern<DatePickerColumnPattern>();
193         CHECK_NULL_VOID(datePickerColumnPattern);
194         datePickerColumnPattern->SetEventCallback(std::move(value));
195     }
196 }
197 
SetChangeCallback(ColumnChangeCallback && value)198 void DatePickerPattern::SetChangeCallback(ColumnChangeCallback&& value)
199 {
200     auto host = GetHost();
201     CHECK_NULL_VOID(host);
202     auto children = host->GetChildren();
203     for (const auto& child : children) {
204         auto stackNode = DynamicCast<FrameNode>(child);
205         CHECK_NULL_VOID(stackNode);
206         auto childNode = stackNode->GetChildAtIndex(1);
207         CHECK_NULL_VOID(childNode);
208         auto datePickerColumnPattern = DynamicCast<FrameNode>(childNode)->GetPattern<DatePickerColumnPattern>();
209         CHECK_NULL_VOID(datePickerColumnPattern);
210         datePickerColumnPattern->SetChangeCallback(std::move(value));
211     }
212 }
213 
OnColorConfigurationUpdate()214 void DatePickerPattern::OnColorConfigurationUpdate()
215 {
216     auto host = GetHost();
217     CHECK_NULL_VOID(host);
218     host->SetNeedCallChildrenUpdate(false);
219     auto context = host->GetContext();
220     CHECK_NULL_VOID(context);
221     auto pickerTheme = context->GetTheme<PickerTheme>();
222     CHECK_NULL_VOID(pickerTheme);
223     auto dialogTheme = context->GetTheme<DialogTheme>();
224     CHECK_NULL_VOID(dialogTheme);
225     auto disappearStyle = pickerTheme->GetDisappearOptionStyle();
226     auto normalStyle = pickerTheme->GetOptionStyle(false, false);
227     auto pickerProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
228     CHECK_NULL_VOID(pickerProperty);
229     pickerProperty->UpdateColor(normalStyle.GetTextColor());
230     pickerProperty->UpdateDisappearColor(disappearStyle.GetTextColor());
231     if (isPicker_) {
232         return;
233     }
234     SetBackgroundColor(dialogTheme->GetBackgroundColor());
235     auto buttonTitleNode = buttonTitleNode_.Upgrade();
236     CHECK_NULL_VOID(buttonTitleNode);
237     auto titleLayoutRenderContext = buttonTitleNode->GetRenderContext();
238     CHECK_NULL_VOID(titleLayoutRenderContext);
239     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) ||
240         !titleLayoutRenderContext->IsUniRenderEnabled()) {
241         titleLayoutRenderContext->UpdateBackgroundColor(dialogTheme->GetButtonBackgroundColor());
242     }
243     auto childButton = buttonTitleNode->GetFirstChild();
244     CHECK_NULL_VOID(childButton);
245     auto ButtonNode = DynamicCast<FrameNode>(childButton);
246     CHECK_NULL_VOID(ButtonNode);
247     auto buttonTitleRenderContext = ButtonNode->GetRenderContext();
248     CHECK_NULL_VOID(buttonTitleRenderContext);
249     buttonTitleRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
250     auto childText = ButtonNode->GetFirstChild();
251     CHECK_NULL_VOID(childText);
252     auto textTitleNode = DynamicCast<FrameNode>(childText);
253     CHECK_NULL_VOID(textTitleNode);
254     auto textLayoutProperty = textTitleNode->GetLayoutProperty<TextLayoutProperty>();
255     CHECK_NULL_VOID(textLayoutProperty);
256     textLayoutProperty->UpdateTextColor(pickerTheme->GetTitleStyle().GetTextColor());
257     auto contentRowNode = contentRowNode_.Upgrade();
258     CHECK_NULL_VOID(contentRowNode);
259     auto layoutRenderContext = contentRowNode->GetRenderContext();
260     CHECK_NULL_VOID(layoutRenderContext);
261     layoutRenderContext->UpdateBackgroundColor(dialogTheme->GetButtonBackgroundColor());
262     OnModifyDone();
263 }
264 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)265 void DatePickerPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
266 {
267     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
268         auto pattern = wp.Upgrade();
269         CHECK_NULL_RETURN(pattern, false);
270         return pattern->OnKeyEvent(event);
271     };
272     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
273 
274     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
275         auto pattern = wp.Upgrade();
276         if (pattern) {
277             pattern->GetInnerFocusPaintRect(paintRect);
278         }
279     };
280     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
281 }
282 
PaintFocusState()283 void DatePickerPattern::PaintFocusState()
284 {
285     auto host = GetHost();
286     CHECK_NULL_VOID(host);
287 
288     RoundRect focusRect;
289     GetInnerFocusPaintRect(focusRect);
290 
291     auto focusHub = host->GetFocusHub();
292     CHECK_NULL_VOID(focusHub);
293     focusHub->PaintInnerFocusState(focusRect);
294 
295     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
296 }
297 
GetInnerFocusPaintRect(RoundRect & paintRect)298 void DatePickerPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
299 {
300     auto host = GetHost();
301     CHECK_NULL_VOID(host);
302     auto childSize = 1.0f;
303     if (!ShowMonthDays()) {
304         childSize = static_cast<float>(host->GetChildren().size());
305     }
306     auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
307     CHECK_NULL_VOID(stackChild);
308     auto pickerChild = DynamicCast<FrameNode>(stackChild->GetLastChild());
309     CHECK_NULL_VOID(pickerChild);
310     auto columnWidth = pickerChild->GetGeometryNode()->GetFrameSize().Width();
311     auto pipeline = PipelineBase::GetCurrentContext();
312     CHECK_NULL_VOID(pipeline);
313     auto pickerTheme = pipeline->GetTheme<PickerTheme>();
314     CHECK_NULL_VOID(pickerTheme);
315     auto frameWidth = host->GetGeometryNode()->GetFrameSize().Width();
316     auto dividerSpacing = pickerTheme->GetDividerSpacing().ConvertToPx();
317     auto pickerThemeWidth = dividerSpacing * 2;
318 
319     auto centerX = (frameWidth / childSize - pickerThemeWidth) / 2 +
320                    pickerChild->GetGeometryNode()->GetFrameRect().Width() * focusKeyID_ +
321                    PRESS_INTERVAL.ConvertToPx() * 2;
322     auto centerY =
323         (host->GetGeometryNode()->GetFrameSize().Height() - dividerSpacing) / 2 + PRESS_INTERVAL.ConvertToPx();
324     float piantRectWidth = (dividerSpacing - PRESS_INTERVAL.ConvertToPx()) * 2;
325     float piantRectHeight = dividerSpacing - PRESS_INTERVAL.ConvertToPx() * 2;
326     if (piantRectWidth > columnWidth) {
327         piantRectWidth = columnWidth;
328         centerX = focusKeyID_ * columnWidth;
329     }
330     paintRect.SetRect(RectF(centerX, centerY, piantRectWidth, piantRectHeight));
331     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
332         static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
333     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
334         static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
335     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
336         static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
337     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()),
338         static_cast<RSScalar>(PRESS_RADIUS.ConvertToPx()));
339 }
340 
OnKeyEvent(const KeyEvent & event)341 bool DatePickerPattern::OnKeyEvent(const KeyEvent& event)
342 {
343     if (event.action != KeyAction::DOWN) {
344         return false;
345     }
346     if (event.code == KeyCode::KEY_DPAD_UP || event.code == KeyCode::KEY_DPAD_DOWN ||
347         event.code == KeyCode::KEY_DPAD_LEFT || event.code == KeyCode::KEY_DPAD_RIGHT ||
348         event.code == KeyCode::KEY_MOVE_HOME || event.code == KeyCode::KEY_MOVE_END) {
349         return HandleDirectionKey(event.code);
350     }
351     return false;
352 }
353 
HandleDirectionKey(KeyCode code)354 bool DatePickerPattern::HandleDirectionKey(KeyCode code)
355 {
356     auto host = GetHost();
357     CHECK_NULL_RETURN(host, false);
358 
359     auto stackChild = DynamicCast<FrameNode>(host->GetChildAtIndex(focusKeyID_));
360     auto pickerChild = DynamicCast<FrameNode>(stackChild->GetChildAtIndex(1));
361     auto pattern = pickerChild->GetPattern<DatePickerColumnPattern>();
362     auto totalOptionCount = GetOptionCount(pickerChild);
363     if (totalOptionCount == 0) {
364         return false;
365     }
366     if (code == KeyCode::KEY_DPAD_UP) {
367         pattern->InnerHandleScroll(false, false);
368         return true;
369     }
370     if (code == KeyCode::KEY_DPAD_DOWN) {
371         pattern->InnerHandleScroll(true, false);
372         return true;
373     }
374     if (code == KeyCode::KEY_MOVE_HOME) {
375         pattern->SetCurrentIndex(1);
376         pattern->InnerHandleScroll(false, false);
377         return true;
378     }
379     if (code == KeyCode::KEY_MOVE_END) {
380         pattern->SetCurrentIndex(totalOptionCount - UNOPTION_COUNT);
381         pattern->InnerHandleScroll(true, false);
382         return true;
383     }
384     if (code == KeyCode::KEY_DPAD_LEFT) {
385         focusKeyID_ -= 1;
386         if (focusKeyID_ < 0) {
387             focusKeyID_ = 0;
388             return false;
389         }
390         PaintFocusState();
391         return true;
392     }
393     if (code == KeyCode::KEY_DPAD_RIGHT) {
394         focusKeyID_ += 1;
395         auto childSize = 1.0f;
396         if (!ShowMonthDays()) {
397             childSize = static_cast<float>(host->GetChildren().size());
398         }
399         if (focusKeyID_ > childSize - 1) {
400             focusKeyID_ = childSize - 1;
401             return false;
402         }
403         PaintFocusState();
404         return true;
405     }
406     return false;
407 }
408 
GetAllChildNode()409 std::unordered_map<std::string, RefPtr<FrameNode>> DatePickerPattern::GetAllChildNode()
410 {
411     std::unordered_map<std::string, RefPtr<FrameNode>> allChildNode;
412     auto host = GetHost();
413     CHECK_NULL_RETURN(host, allChildNode);
414     auto children = host->GetChildren();
415     if (children.size() != CHILD_SIZE) {
416         return allChildNode;
417     }
418     auto iter = children.begin();
419     auto year = (*iter);
420     CHECK_NULL_RETURN(year, allChildNode);
421     iter++;
422     auto month = *iter;
423     CHECK_NULL_RETURN(month, allChildNode);
424     iter++;
425     auto day = *iter;
426     CHECK_NULL_RETURN(day, allChildNode);
427     auto stackYear = DynamicCast<FrameNode>(year);
428     auto yearNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
429     auto stackMonth = DynamicCast<FrameNode>(month);
430     auto monthNode = DynamicCast<FrameNode>(stackMonth->GetChildAtIndex(1));
431     auto stackDay = DynamicCast<FrameNode>(day);
432     auto dayNode = DynamicCast<FrameNode>(stackDay->GetChildAtIndex(1));
433 
434     CHECK_NULL_RETURN(yearNode, allChildNode);
435     CHECK_NULL_RETURN(monthNode, allChildNode);
436     CHECK_NULL_RETURN(dayNode, allChildNode);
437     allChildNode["year"] = yearNode;
438     allChildNode["month"] = monthNode;
439     allChildNode["day"] = dayNode;
440     return allChildNode;
441 }
442 
FlushColumn()443 void DatePickerPattern::FlushColumn()
444 {
445     auto host = GetHost();
446     CHECK_NULL_VOID(host);
447     auto allChildNode = GetAllChildNode();
448 
449     auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
450     CHECK_NULL_VOID(dataPickerRowLayoutProperty);
451     auto lunarDate = dataPickerRowLayoutProperty->GetSelectedDate().value_or(SolarToLunar(GetSelectedDate()));
452     AdjustLunarDate(lunarDate);
453     std::string language = Localization::GetInstance()->GetLanguage();
454     if (dataPickerRowLayoutProperty->GetLunar().value_or(false) && (strcmp(language.c_str(), "zh") == 0)) {
455         LunarColumnsBuilding(lunarDate);
456     } else {
457         SolarColumnsBuilding(LunarToSolar(lunarDate));
458     }
459 
460     auto yearNode = allChildNode["year"];
461     auto monthNode = allChildNode["month"];
462     auto dayNode = allChildNode["day"];
463     CHECK_NULL_VOID(yearNode);
464     CHECK_NULL_VOID(monthNode);
465     CHECK_NULL_VOID(dayNode);
466     auto yearColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
467     CHECK_NULL_VOID(yearColumnPattern);
468     auto monthColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
469     CHECK_NULL_VOID(monthColumnPattern);
470     auto dayColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
471     CHECK_NULL_VOID(dayColumnPattern);
472 
473     yearColumnPattern->SetShowCount(GetShowCount());
474     monthColumnPattern->SetShowCount(GetShowCount());
475     dayColumnPattern->SetShowCount(GetShowCount());
476     yearColumnPattern->FlushCurrentOptions();
477     monthColumnPattern->FlushCurrentOptions();
478     dayColumnPattern->FlushCurrentOptions();
479 }
480 
FlushMonthDaysColumn()481 void DatePickerPattern::FlushMonthDaysColumn()
482 {
483     auto host = GetHost();
484     CHECK_NULL_VOID(host);
485 
486     auto children = host->GetChildren();
487     if (children.size() <= SINGLE_CHILD_SIZE) {
488         return;
489     }
490     auto iter = children.begin();
491     auto monthDays = (*iter);
492     CHECK_NULL_VOID(monthDays);
493     iter++;
494     auto year = *iter;
495     CHECK_NULL_VOID(year);
496     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
497     auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
498     auto stackYear = DynamicCast<FrameNode>(year);
499     auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
500     CHECK_NULL_VOID(monthDaysNode);
501     CHECK_NULL_VOID(yearDaysNode);
502     auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
503     CHECK_NULL_VOID(dataPickerRowLayoutProperty);
504     std::string language = Localization::GetInstance()->GetLanguage();
505     if (dataPickerRowLayoutProperty->GetLunar().value_or(false) && (strcmp(language.c_str(), "zh") == 0)) {
506         LunarMonthDaysColumnBuilding(
507             dataPickerRowLayoutProperty->GetSelectedDate().value_or(SolarToLunar(GetSelectedDate())));
508     } else {
509         SolarMonthDaysColumnsBuilding(
510             LunarToSolar(dataPickerRowLayoutProperty->GetSelectedDate().value_or(SolarToLunar(GetSelectedDate()))));
511     }
512 
513     auto monthDaysColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
514     auto yearColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
515     CHECK_NULL_VOID(monthDaysColumnPattern);
516     CHECK_NULL_VOID(yearColumnPattern);
517 
518     monthDaysColumnPattern->SetShowCount(GetShowCount());
519     yearColumnPattern->SetShowCount(GetShowCount());
520     monthDaysColumnPattern->FlushCurrentOptions();
521     yearColumnPattern->FlushCurrentOptions();
522 }
523 
FireChangeEvent(bool refresh)524 void DatePickerPattern::FireChangeEvent(bool refresh)
525 {
526     if (refresh) {
527         auto datePickerEventHub = GetEventHub<DatePickerEventHub>();
528         CHECK_NULL_VOID(datePickerEventHub);
529         auto str = GetSelectedObject(true);
530         auto info = std::make_shared<DatePickerChangeEvent>(str);
531         datePickerEventHub->FireChangeEvent(info.get());
532         datePickerEventHub->FireDialogChangeEvent(str);
533         firedDateStr_ = str;
534     }
535 }
536 
ShowTitle(int32_t titleId)537 void DatePickerPattern::ShowTitle(int32_t titleId)
538 {
539     if (HasTitleNode()) {
540         auto textTitleNode = FrameNode::GetOrCreateFrameNode(
541             V2::TEXT_ETS_TAG, titleId, []() { return AceType::MakeRefPtr<TextPattern>(); });
542         auto dateStr = GetCurrentDate();
543         CHECK_NULL_VOID(textTitleNode);
544         auto textLayoutProperty = textTitleNode->GetLayoutProperty<TextLayoutProperty>();
545         CHECK_NULL_VOID(textLayoutProperty);
546         textLayoutProperty->UpdateContent(dateStr.ToString(false));
547         textTitleNode->MarkModifyDone();
548         textTitleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
549     }
550 }
551 
OnDataLinking(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)552 void DatePickerPattern::OnDataLinking(
553     const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
554 {
555     auto allChildNode = GetAllChildNode();
556     auto yearNode = allChildNode["year"];
557     auto monthNode = allChildNode["month"];
558     auto dayNode = allChildNode["day"];
559     CHECK_NULL_VOID(yearNode);
560     CHECK_NULL_VOID(monthNode);
561     CHECK_NULL_VOID(dayNode);
562     if (tag == yearNode) {
563         HandleYearChange(isAdd, index, resultTags);
564         return;
565     }
566 
567     if (tag == monthNode) {
568         HandleMonthChange(isAdd, index, resultTags);
569         return;
570     }
571 
572     if (tag == dayNode) {
573         HandleDayChange(isAdd, index, resultTags);
574         return;
575     }
576 }
577 
HandleMonthDaysChange(const RefPtr<FrameNode> & tag,bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)578 void DatePickerPattern::HandleMonthDaysChange(
579     const RefPtr<FrameNode>& tag, bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
580 {
581     auto host = GetHost();
582     CHECK_NULL_VOID(host);
583 
584     auto children = host->GetChildren();
585     if (children.size() <= SINGLE_CHILD_SIZE) {
586         return;
587     }
588     auto iter = children.begin();
589     auto monthDays = (*iter);
590     CHECK_NULL_VOID(monthDays);
591 
592     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
593     auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
594     if (tag != monthDaysNode) {
595         return;
596     }
597 
598     if (IsShowLunar()) {
599         HandleLunarMonthDaysChange(isAdd, index);
600     } else {
601         HandleSolarMonthDaysChange(isAdd, index);
602     }
603 
604     resultTags.emplace_back(monthDaysNode);
605 }
606 
GetSelectedObject(bool isColumnChange,int status) const607 std::string DatePickerPattern::GetSelectedObject(bool isColumnChange, int status) const
608 {
609     auto date = selectedDate_;
610     if (isColumnChange) {
611         date = GetCurrentDate();
612     }
613     // W3C's month is between 0 to 11, need to reduce one.
614     date.SetMonth(date.GetMonth() - 1);
615 
616     auto dateTimeString = std::string("{\"year\":") + std::to_string(date.GetYear()) +
617                           ",\"month\":" + std::to_string(date.GetMonth()) + ",\"day\":" + std::to_string(date.GetDay());
618     auto pickTime = PickerTime::Current();
619     if (showTime_) {
620         auto host = GetHost();
621         CHECK_NULL_RETURN(host, date.ToString(true, status));
622         if (showMonthDays_) {
623             auto pickerRow = host->GetParent();
624             CHECK_NULL_RETURN(pickerRow, date.ToString(true, status));
625             auto timeNode = AceType::DynamicCast<FrameNode>(pickerRow->GetChildAtIndex(1));
626             CHECK_NULL_RETURN(timeNode, date.ToString(true, status));
627             auto timePickerPattern = timeNode->GetPattern<TimePickerRowPattern>();
628             CHECK_NULL_RETURN(timePickerPattern, date.ToString(true, status));
629             pickTime = timePickerPattern->GetCurrentTime();
630         } else {
631             auto pickerStack = host->GetParent();
632             CHECK_NULL_RETURN(pickerStack, date.ToString(true, status));
633             auto pickerRow = pickerStack->GetLastChild();
634             CHECK_NULL_RETURN(pickerRow, date.ToString(true, status));
635             auto timeNode = AceType::DynamicCast<FrameNode>(pickerRow->GetChildAtIndex(1));
636             CHECK_NULL_RETURN(timeNode, date.ToString(true, status));
637             auto timePickerPattern = timeNode->GetPattern<TimePickerRowPattern>();
638             CHECK_NULL_RETURN(timePickerPattern, date.ToString(true, status));
639             pickTime = timePickerPattern->GetCurrentTime();
640         }
641     }
642     dateTimeString += std::string(",\"hour\":") + std::to_string(pickTime.GetHour()) +
643                       ",\"minute\":" + std::to_string(pickTime.GetMinute()) + ",\"status\":" + std::to_string(status) +
644                       "}";
645     return dateTimeString;
646 }
647 
HandleDayChange(bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)648 void DatePickerPattern::HandleDayChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
649 {
650     auto allChildNode = GetAllChildNode();
651     auto yearNode = allChildNode["year"];
652     auto monthNode = allChildNode["month"];
653     auto dayNode = allChildNode["day"];
654     CHECK_NULL_VOID(yearNode);
655     CHECK_NULL_VOID(monthNode);
656     CHECK_NULL_VOID(dayNode);
657     if (IsShowLunar()) {
658         HandleLunarDayChange(isAdd, index);
659     } else {
660         HandleSolarDayChange(isAdd, index);
661     }
662     resultTags.emplace_back(yearNode);
663     resultTags.emplace_back(monthNode);
664     resultTags.emplace_back(dayNode);
665 }
666 
HandleSolarDayChange(bool isAdd,uint32_t index)667 void DatePickerPattern::HandleSolarDayChange(bool isAdd, uint32_t index)
668 {
669     auto allChildNode = GetAllChildNode();
670     auto yearNode = allChildNode["year"];
671     auto monthNode = allChildNode["month"];
672     auto dayNode = allChildNode["day"];
673 
674     CHECK_NULL_VOID(yearNode);
675     CHECK_NULL_VOID(monthNode);
676     CHECK_NULL_VOID(dayNode);
677     auto yearDatePickerColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
678     auto monthDatePickerColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
679     auto dayDatePickerColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
680     CHECK_NULL_VOID(yearDatePickerColumnPattern);
681     CHECK_NULL_VOID(monthDatePickerColumnPattern);
682     CHECK_NULL_VOID(dayDatePickerColumnPattern);
683 
684     auto date = GetCurrentDate();
685     if (isAdd && index == 0) {
686         date.SetMonth(date.GetMonth() + 1);   // add to next month
687         if (date.GetMonth() > 12) {           // invalidate month, max month is 12
688             date.SetMonth(1);                 // first month is 1
689             date.SetYear(date.GetYear() + 1); // add to next year
690             if (date.GetYear() > endDateSolar_.GetYear()) {
691                 date.SetYear(startDateSolar_.GetYear());
692             }
693         }
694     }
695     if (!isAdd &&
696         dayDatePickerColumnPattern->GetCurrentIndex() == GetOptionCount(dayNode) - 1) { // last index is count - 1
697         date.SetMonth(date.GetMonth() - 1);                                             // reduce to previous month
698         if (date.GetMonth() == 0) {                                                     // min month is 1, invalidate
699             date.SetMonth(12);                                                          // set to be the last month
700             date.SetYear(date.GetYear() - 1);                                           // reduce to previous year
701             if (date.GetYear() < startDateSolar_.GetYear()) {
702                 date.SetYear(endDateSolar_.GetYear());
703             }
704         }
705         date.SetDay(PickerDate::GetMaxDay(date.GetYear(), date.GetMonth())); // reduce to previous month's last day
706     }
707     uint32_t maxDay = PickerDate::GetMaxDay(date.GetYear(), date.GetMonth());
708     if (date.GetDay() > maxDay) {
709         date.SetDay(maxDay);
710     }
711     AdjustSolarDate(date);
712     SolarColumnsBuilding(date);
713 }
714 
HandleLunarDayChange(bool isAdd,uint32_t index)715 void DatePickerPattern::HandleLunarDayChange(bool isAdd, uint32_t index)
716 {
717     if (isAdd) {
718         HandleAddLunarDayChange(index);
719     } else {
720         HandleReduceLunarDayChange(index);
721     }
722 }
723 
HandleReduceLunarDayChange(uint32_t index)724 void DatePickerPattern::HandleReduceLunarDayChange(uint32_t index)
725 {
726     auto allChildNode = GetAllChildNode();
727     auto yearNode = allChildNode["year"];
728     auto monthNode = allChildNode["month"];
729     auto dayNode = allChildNode["day"];
730 
731     CHECK_NULL_VOID(yearNode);
732     CHECK_NULL_VOID(monthNode);
733     CHECK_NULL_VOID(dayNode);
734 
735     auto yearDatePickerColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
736     auto monthDatePickerColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
737     auto dayDatePickerColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
738 
739     uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
740     auto lunarDate = GetCurrentLunarDate(nowLunarYear);
741     uint32_t lunarLeapMonth = 0;
742     bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, lunarLeapMonth);
743     if (dayDatePickerColumnPattern->GetCurrentIndex() == GetOptionCount(dayNode) - 1) { // max index is count - 1
744         if (monthDatePickerColumnPattern->GetCurrentIndex() == 0) {
745             lunarDate.year = lunarDate.year - 1; // reduce to previous year
746             if (lunarDate.year < startDateLunar_.year) {
747                 lunarDate.year = endDateLunar_.year;
748             }
749             lunarDate.month = 12; // set to be previous year's max month
750             lunarDate.isLeapMonth = false;
751             if (LunarCalculator::GetLunarLeapMonth(lunarDate.year) == 12) { // leap 12th month
752                 lunarDate.isLeapMonth = true;
753             }
754             lunarDate.day = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
755         } else {
756             if (lunarDate.isLeapMonth) {
757                 lunarDate.isLeapMonth = false;
758             } else if (!hasLeapMonth) {
759                 lunarDate.month = lunarDate.month - 1;          // reduce to previous month
760             } else if (lunarLeapMonth == lunarDate.month - 1) { // leap month is previous month
761                 lunarDate.isLeapMonth = true;
762                 lunarDate.month = lunarLeapMonth;
763             } else {
764                 lunarDate.month = lunarDate.month - 1; // reduce to previous month
765             }
766             lunarDate.day = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
767         }
768     }
769 
770     AdjustLunarDate(lunarDate);
771     LunarColumnsBuilding(lunarDate);
772 }
773 
HandleAddLunarDayChange(uint32_t index)774 void DatePickerPattern::HandleAddLunarDayChange(uint32_t index)
775 {
776     auto allChildNode = GetAllChildNode();
777     auto yearNode = allChildNode["year"];
778     auto monthNode = allChildNode["month"];
779     auto dayNode = allChildNode["day"];
780 
781     CHECK_NULL_VOID(yearNode);
782     CHECK_NULL_VOID(monthNode);
783     CHECK_NULL_VOID(dayNode);
784 
785     auto yearDatePickerColumnPattern = yearNode->GetPattern<DatePickerColumnPattern>();
786     auto monthDatePickerColumnPattern = monthNode->GetPattern<DatePickerColumnPattern>();
787     auto dayDatePickerColumnPattern = dayNode->GetPattern<DatePickerColumnPattern>();
788 
789     uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
790     auto lunarDate = GetCurrentLunarDate(nowLunarYear);
791     uint32_t lunarLeapMonth = 0;
792     bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, lunarLeapMonth);
793     if (index == 0) {
794         if (monthDatePickerColumnPattern->GetCurrentIndex() ==
795             GetOptionCount(monthNode) - 1) {     // max index is count - 1
796             lunarDate.year = lunarDate.year + 1; // add to next year
797             if (lunarDate.year > endDateLunar_.year) {
798                 lunarDate.year = startDateLunar_.year;
799             }
800             lunarDate.month = 1; // first month
801             lunarDate.isLeapMonth = false;
802         } else {
803             if (lunarDate.isLeapMonth) {
804                 lunarDate.month = lunarDate.month + 1; // add to next month
805                 lunarDate.isLeapMonth = false;
806             } else if (!hasLeapMonth) {
807                 lunarDate.month = lunarDate.month + 1; // add to next month
808             } else if (lunarLeapMonth == lunarDate.month) {
809                 lunarDate.isLeapMonth = true;
810             } else {
811                 lunarDate.month = lunarDate.month + 1; // add to next month
812             }
813         }
814     }
815 
816     AdjustLunarDate(lunarDate);
817     LunarColumnsBuilding(lunarDate);
818 }
819 
HandleSolarMonthDaysChange(bool isAdd,uint32_t index)820 void DatePickerPattern::HandleSolarMonthDaysChange(bool isAdd, uint32_t index)
821 {
822     auto host = GetHost();
823     CHECK_NULL_VOID(host);
824 
825     auto children = host->GetChildren();
826     if (children.size() <= SINGLE_CHILD_SIZE) {
827         return;
828     }
829     auto iter = children.begin();
830     auto monthDays = (*iter);
831     CHECK_NULL_VOID(monthDays);
832     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
833     CHECK_NULL_VOID(stackMonthDays);
834     auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
835     CHECK_NULL_VOID(monthDaysNode);
836     auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
837     CHECK_NULL_VOID(monthDaysDatePickerColumnPattern);
838 
839     auto date = GetCurrentDate();
840 
841     if (isAdd && index == 0) {
842         // add to next year
843         date.SetYear(date.GetYear() + 1); // add to next year
844         if (date.GetYear() > endDateSolar_.GetYear()) {
845             date.SetYear(startDateSolar_.GetYear());
846         }
847     }
848     if (!isAdd && monthDaysDatePickerColumnPattern->GetCurrentIndex() == GetOptionCount(monthDaysNode) - 1) {
849         // reduce to previous year
850         date.SetYear(date.GetYear() - 1);
851         if (date.GetYear() < startDateSolar_.GetYear()) {
852             date.SetYear(endDateSolar_.GetYear());
853         }
854         // reduce to previous year's last day
855         date.SetMonth(MAX_MONTH);
856         date.SetDay(PickerDate::GetMaxDay(date.GetYear(), date.GetMonth()));
857     }
858     uint32_t maxDay = PickerDate::GetMaxDay(date.GetYear(), date.GetMonth());
859     if (date.GetDay() > maxDay) {
860         date.SetDay(maxDay);
861     }
862     AdjustSolarDate(date);
863     SolarMonthDaysColumnsBuilding(date);
864 }
865 
HandleLunarMonthDaysChange(bool isAdd,uint32_t index)866 void DatePickerPattern::HandleLunarMonthDaysChange(bool isAdd, uint32_t index)
867 {
868     if (isAdd) {
869         HandleAddLunarMonthDaysChange(index);
870     } else {
871         HandleReduceLunarMonthDaysChange(index);
872     }
873 }
874 
HandleAddLunarMonthDaysChange(uint32_t index)875 void DatePickerPattern::HandleAddLunarMonthDaysChange(uint32_t index)
876 {
877     auto host = GetHost();
878     CHECK_NULL_VOID(host);
879 
880     auto children = host->GetChildren();
881     if (children.size() <= SINGLE_CHILD_SIZE) {
882         return;
883     }
884     auto iter = children.begin();
885     auto monthDays = (*iter);
886     CHECK_NULL_VOID(monthDays);
887     iter++;
888     auto year = *iter;
889     CHECK_NULL_VOID(year);
890     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
891     auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
892     auto stackYear = DynamicCast<FrameNode>(year);
893     auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
894     CHECK_NULL_VOID(monthDaysNode);
895     CHECK_NULL_VOID(yearDaysNode);
896 
897     auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
898     auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
899 
900     uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
901     auto lunarDate = GetCurrentLunarDateByMonthDaysColumn(nowLunarYear);
902     if (index == 0) {
903         lunarDate.year = lunarDate.year + 1; // add to next year
904         if (lunarDate.year > endDateLunar_.year) {
905             lunarDate.year = startDateLunar_.year;
906         }
907         lunarDate.month = 1;
908         lunarDate.isLeapMonth = false;
909     }
910 
911     AdjustLunarDate(lunarDate);
912     LunarMonthDaysColumnBuilding(lunarDate);
913 }
914 
HandleReduceLunarMonthDaysChange(uint32_t index)915 void DatePickerPattern::HandleReduceLunarMonthDaysChange(uint32_t index)
916 {
917     auto host = GetHost();
918     CHECK_NULL_VOID(host);
919 
920     auto children = host->GetChildren();
921     if (children.size() <= SINGLE_CHILD_SIZE) {
922         return;
923     }
924     auto iter = children.begin();
925     auto monthDays = (*iter);
926     CHECK_NULL_VOID(monthDays);
927     iter++;
928     auto year = *iter;
929     CHECK_NULL_VOID(year);
930     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
931     auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
932     auto stackYear = DynamicCast<FrameNode>(year);
933     auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
934     CHECK_NULL_VOID(monthDaysNode);
935     CHECK_NULL_VOID(yearDaysNode);
936 
937     auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
938     auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
939     CHECK_NULL_VOID(monthDaysDatePickerColumnPattern);
940     CHECK_NULL_VOID(yearDatePickerColumnPattern);
941 
942     uint32_t nowLunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
943     auto lunarDate = GetCurrentLunarDateByMonthDaysColumn(nowLunarYear);
944     if (monthDaysDatePickerColumnPattern->GetCurrentIndex() == GetOptionCount(monthDaysNode) - 1) {
945         lunarDate.year = lunarDate.year - 1; // reduce to previous year
946         if (lunarDate.year < startDateLunar_.year) {
947             lunarDate.year = endDateLunar_.year;
948         }
949         lunarDate.month = MAX_MONTH; // set to be previous year's max month
950         lunarDate.isLeapMonth = false;
951         if (LunarCalculator::GetLunarLeapMonth(lunarDate.year) == 12) { // leap 12th month
952             lunarDate.isLeapMonth = true;
953         }
954         lunarDate.day = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
955     }
956 
957     AdjustLunarDate(lunarDate);
958     LunarMonthDaysColumnBuilding(lunarDate);
959 }
960 
HandleYearChange(bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)961 void DatePickerPattern::HandleYearChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
962 {
963     auto allChildNode = GetAllChildNode();
964     auto yearNode = allChildNode["year"];
965     auto monthNode = allChildNode["month"];
966     auto dayNode = allChildNode["day"];
967 
968     CHECK_NULL_VOID(yearNode);
969     CHECK_NULL_VOID(monthNode);
970     CHECK_NULL_VOID(dayNode);
971     if (IsShowLunar()) {
972         HandleLunarYearChange(isAdd, index);
973     } else {
974         HandleSolarYearChange(isAdd, index);
975     }
976     resultTags.emplace_back(yearNode);
977     resultTags.emplace_back(monthNode);
978     resultTags.emplace_back(dayNode);
979 }
980 
HandleMonthChange(bool isAdd,uint32_t index,std::vector<RefPtr<FrameNode>> & resultTags)981 void DatePickerPattern::HandleMonthChange(bool isAdd, uint32_t index, std::vector<RefPtr<FrameNode>>& resultTags)
982 {
983     auto allChildNode = GetAllChildNode();
984     auto yearNode = allChildNode["year"];
985     auto monthNode = allChildNode["month"];
986     auto dayNode = allChildNode["day"];
987 
988     CHECK_NULL_VOID(yearNode);
989     CHECK_NULL_VOID(monthNode);
990     CHECK_NULL_VOID(dayNode);
991     if (IsShowLunar()) {
992         HandleLunarMonthChange(isAdd, index);
993     } else {
994         HandleSolarMonthChange(isAdd, index);
995     }
996     resultTags.emplace_back(yearNode);
997     resultTags.emplace_back(monthNode);
998     resultTags.emplace_back(dayNode);
999 }
1000 
HandleSolarMonthChange(bool isAdd,uint32_t index)1001 void DatePickerPattern::HandleSolarMonthChange(bool isAdd, uint32_t index)
1002 {
1003     auto date = GetCurrentDate();
1004     if (isAdd && date.GetMonth() == 1) {  // first month is 1
1005         date.SetYear(date.GetYear() + 1); // add 1 year, the next year
1006         if (date.GetYear() > endDateSolar_.GetYear()) {
1007             date.SetYear(startDateSolar_.GetYear());
1008         }
1009     }
1010     if (!isAdd && date.GetMonth() == 12) { // the last month is 12
1011         date.SetYear(date.GetYear() - 1);  // reduce 1 year, the previous year
1012         if (date.GetYear() < startDateSolar_.GetYear()) {
1013             date.SetYear(endDateSolar_.GetYear());
1014         }
1015     }
1016     uint32_t maxDay = PickerDate::GetMaxDay(date.GetYear(), date.GetMonth());
1017     if (date.GetDay() > maxDay) {
1018         date.SetDay(maxDay);
1019     }
1020     AdjustSolarDate(date);
1021     SolarColumnsBuilding(date);
1022 }
1023 
HandleLunarMonthChange(bool isAdd,uint32_t index)1024 void DatePickerPattern::HandleLunarMonthChange(bool isAdd, uint32_t index)
1025 {
1026     auto allChildNode = GetAllChildNode();
1027     auto yearNode = allChildNode["year"];
1028     auto monthNode = allChildNode["month"];
1029     auto dayNode = allChildNode["day"];
1030 
1031     CHECK_NULL_VOID(yearNode);
1032     CHECK_NULL_VOID(monthNode);
1033     CHECK_NULL_VOID(dayNode);
1034 
1035     auto yearColumn = yearNode->GetPattern<DatePickerColumnPattern>();
1036     CHECK_NULL_VOID(yearColumn);
1037     uint32_t nowLunarYear = startDateLunar_.year + yearColumn->GetCurrentIndex();
1038     auto lunarDate = GetCurrentLunarDate(nowLunarYear);
1039     if (isAdd && index == 0) {
1040         lunarDate.year = lunarDate.year + 1; // add to next year
1041         if (lunarDate.year > endDateLunar_.year) {
1042             lunarDate.year = startDateLunar_.year;
1043         }
1044     }
1045     if (!isAdd && index == GetOptionCount(monthNode) - 1) {
1046         lunarDate.year = lunarDate.year - 1; // reduce to previous year
1047         if (lunarDate.year < startDateLunar_.year) {
1048             lunarDate.year = endDateLunar_.year;
1049         }
1050     }
1051     uint32_t lunarLeapMonth = 0;
1052     bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, lunarLeapMonth);
1053     if (!hasLeapMonth && lunarDate.isLeapMonth) {
1054         lunarDate.isLeapMonth = false;
1055     }
1056     uint32_t maxDay = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
1057     if (lunarDate.day > maxDay) {
1058         lunarDate.day = maxDay;
1059     }
1060 
1061     AdjustLunarDate(lunarDate);
1062     LunarColumnsBuilding(lunarDate);
1063 }
1064 
HandleLunarYearChange(bool isAdd,uint32_t index)1065 void DatePickerPattern::HandleLunarYearChange(bool isAdd, uint32_t index)
1066 {
1067     auto allChildNode = GetAllChildNode();
1068     auto yearNode = allChildNode["year"];
1069     CHECK_NULL_VOID(yearNode);
1070     auto yearColumn = DynamicCast<FrameNode>(yearNode);
1071     uint32_t lastYearIndex = index;
1072     auto optionCount = GetOptionCount(yearColumn);
1073     if (isAdd) { // need reduce one index
1074         lastYearIndex = optionCount != 0 ? (GetOptionCount(yearColumn) + lastYearIndex - 1) % optionCount : 0;
1075     } else { // need add one index
1076         lastYearIndex = optionCount != 0 ? (GetOptionCount(yearColumn) + lastYearIndex + 1) % optionCount : 0;
1077     }
1078     uint32_t lastLunarYear = startDateLunar_.year + lastYearIndex;
1079     auto lunarDate = GetCurrentLunarDate(lastLunarYear);
1080     uint32_t nowLeapMonth = 0;
1081     bool hasLeapMonth = GetLunarLeapMonth(lunarDate.year, nowLeapMonth);
1082     if (!hasLeapMonth && lunarDate.isLeapMonth) {
1083         lunarDate.isLeapMonth = false;
1084     }
1085     uint32_t nowMaxDay = GetLunarMaxDay(lunarDate.year, lunarDate.month, lunarDate.isLeapMonth);
1086     if (lunarDate.day > nowMaxDay) {
1087         lunarDate.day = nowMaxDay;
1088     }
1089 
1090     AdjustLunarDate(lunarDate);
1091     LunarColumnsBuilding(lunarDate);
1092 }
1093 
GetCurrentLunarDate(uint32_t lunarYear) const1094 LunarDate DatePickerPattern::GetCurrentLunarDate(uint32_t lunarYear) const
1095 {
1096     LunarDate lunarResult;
1097     auto host = GetHost();
1098     CHECK_NULL_RETURN(host, lunarResult);
1099     auto children = host->GetChildren();
1100     auto iter = children.begin();
1101     auto year = (*iter);
1102     CHECK_NULL_RETURN(year, lunarResult);
1103     std::advance(iter, 1);
1104     auto month = *iter;
1105     CHECK_NULL_RETURN(month, lunarResult);
1106     std::advance(iter, 1);
1107     auto day = *iter;
1108     CHECK_NULL_RETURN(day, lunarResult);
1109 
1110     auto stackYear = DynamicCast<FrameNode>(year);
1111     auto yearColumn = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1112     auto stackMonth = DynamicCast<FrameNode>(month);
1113     auto monthColumn = DynamicCast<FrameNode>(stackMonth->GetChildAtIndex(1));
1114     auto stackDay = DynamicCast<FrameNode>(day);
1115     auto dayColumn = DynamicCast<FrameNode>(stackDay->GetChildAtIndex(1));
1116     CHECK_NULL_RETURN(yearColumn, lunarResult);
1117     CHECK_NULL_RETURN(monthColumn, lunarResult);
1118     CHECK_NULL_RETURN(dayColumn, lunarResult);
1119 
1120     auto yearDatePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1121     auto monthDatePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1122     auto dayDatePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1123     CHECK_NULL_RETURN(yearDatePickerColumnPattern, lunarResult);
1124     CHECK_NULL_RETURN(monthDatePickerColumnPattern, lunarResult);
1125     CHECK_NULL_RETURN(dayDatePickerColumnPattern, lunarResult);
1126 
1127     uint32_t lunarLeapMonth = 0;
1128     bool hasLeapMonth = GetLunarLeapMonth(lunarYear, lunarLeapMonth);
1129     lunarResult.isLeapMonth = false;
1130     if (!hasLeapMonth) {
1131         lunarResult.month =
1132             monthDatePickerColumnPattern->GetCurrentIndex() + 1; // month from 1 to 12, index from 0 to 11
1133     } else {
1134         if (monthDatePickerColumnPattern->GetCurrentIndex() == lunarLeapMonth) {
1135             lunarResult.isLeapMonth = true;
1136             lunarResult.month = lunarLeapMonth;
1137         } else if (monthDatePickerColumnPattern->GetCurrentIndex() < lunarLeapMonth) {
1138             lunarResult.month =
1139                 monthDatePickerColumnPattern->GetCurrentIndex() + 1; // month start from 1, index start from 0
1140         } else {
1141             lunarResult.month = monthDatePickerColumnPattern->GetCurrentIndex();
1142         }
1143     }
1144     lunarResult.year = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1145     lunarResult.day = dayDatePickerColumnPattern->GetCurrentIndex() + 1; // day start form 1, index start from 0
1146     return lunarResult;
1147 }
1148 
HandleSolarYearChange(bool isAdd,uint32_t index)1149 void DatePickerPattern::HandleSolarYearChange(bool isAdd, uint32_t index)
1150 {
1151     auto date = GetCurrentDate();
1152     bool leapYear = PickerDate::IsLeapYear(date.GetYear());
1153 
1154     if (date.GetMonth() == 2 && !leapYear && date.GetDay() > 28) { // invalidate of 2th month
1155         date.SetDay(28); // the max day of the 2th month of none leap year is 28
1156     }
1157 
1158     AdjustSolarDate(date);
1159     SolarColumnsBuilding(date);
1160 }
1161 
GetCurrentDate() const1162 PickerDate DatePickerPattern::GetCurrentDate() const
1163 {
1164     if (ShowMonthDays()) {
1165         return GetCurrentDateByMonthDaysColumn();
1166     } else {
1167         return GetCurrentDateByYearMonthDayColumn();
1168     }
1169 }
1170 
GetCurrentDateByYearMonthDayColumn() const1171 PickerDate DatePickerPattern::GetCurrentDateByYearMonthDayColumn() const
1172 {
1173     PickerDate currentDate;
1174     auto host = GetHost();
1175     CHECK_NULL_RETURN(host, currentDate);
1176     auto children = host->GetChildren();
1177     if (children.size() != CHILD_SIZE) {
1178         return currentDate;
1179     }
1180     auto iter = children.begin();
1181     auto year = (*iter);
1182     CHECK_NULL_RETURN(year, currentDate);
1183     iter++;
1184     auto month = *iter;
1185     CHECK_NULL_RETURN(month, currentDate);
1186     iter++;
1187     auto day = *iter;
1188     CHECK_NULL_RETURN(day, currentDate);
1189 
1190     auto stackYear = DynamicCast<FrameNode>(year);
1191     auto yearColumn = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1192     auto stackMonth = DynamicCast<FrameNode>(month);
1193     auto monthColumn = DynamicCast<FrameNode>(stackMonth->GetChildAtIndex(1));
1194     auto stackDay = DynamicCast<FrameNode>(day);
1195     auto dayColumn = DynamicCast<FrameNode>(stackDay->GetChildAtIndex(1));
1196     CHECK_NULL_RETURN(yearColumn, currentDate);
1197     CHECK_NULL_RETURN(monthColumn, currentDate);
1198     CHECK_NULL_RETURN(dayColumn, currentDate);
1199     auto yearDatePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1200     auto monthDatePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1201     auto dayDatePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1202     CHECK_NULL_RETURN(yearDatePickerColumnPattern, currentDate);
1203     CHECK_NULL_RETURN(monthDatePickerColumnPattern, currentDate);
1204     CHECK_NULL_RETURN(dayDatePickerColumnPattern, currentDate);
1205     if (!IsShowLunar()) {
1206         currentDate.SetYear(startDateSolar_.GetYear() + yearDatePickerColumnPattern->GetCurrentIndex());
1207         currentDate.SetMonth(
1208             monthDatePickerColumnPattern->GetCurrentIndex() + 1); // month from 1 to 12, index from 0 to 11.
1209         currentDate.SetDay(dayDatePickerColumnPattern->GetCurrentIndex() + 1); // day from 1 to 31, index from 0 to 30.
1210         return currentDate;
1211     }
1212 
1213     uint32_t lunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1214     return LunarToSolar(GetCurrentLunarDate(lunarYear));
1215 }
1216 
GetCurrentDateByMonthDaysColumn() const1217 PickerDate DatePickerPattern::GetCurrentDateByMonthDaysColumn() const
1218 {
1219     PickerDate currentDate;
1220     auto host = GetHost();
1221     CHECK_NULL_RETURN(host, currentDate);
1222 
1223     auto children = host->GetChildren();
1224     if (children.size() <= SINGLE_CHILD_SIZE) {
1225         return currentDate;
1226     }
1227     auto iter = children.begin();
1228     auto monthDays = (*iter);
1229     CHECK_NULL_RETURN(monthDays, currentDate);
1230     iter++;
1231     auto year = *iter;
1232     CHECK_NULL_RETURN(year, currentDate);
1233     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1234     auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
1235     auto stackYear = DynamicCast<FrameNode>(year);
1236     auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1237     CHECK_NULL_RETURN(monthDaysNode, currentDate);
1238     CHECK_NULL_RETURN(yearDaysNode, currentDate);
1239 
1240     auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
1241     auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
1242     CHECK_NULL_RETURN(yearDatePickerColumnPattern, currentDate);
1243     CHECK_NULL_RETURN(monthDaysDatePickerColumnPattern, currentDate);
1244 
1245     if (!IsShowLunar()) {
1246         currentDate.SetYear(startDateSolar_.GetYear() + yearDatePickerColumnPattern->GetCurrentIndex());
1247         auto monthDaysIndex = monthDaysDatePickerColumnPattern->GetCurrentIndex();
1248 
1249         uint32_t month = 1;
1250         for (; month <= 12; ++month) { // month start from 1 to 12
1251             uint32_t daysInMonth = PickerDate::GetMaxDay(currentDate.GetYear(), month);
1252             if (monthDaysIndex < daysInMonth) {
1253                 break;
1254             } else {
1255                 monthDaysIndex -= daysInMonth;
1256             }
1257         }
1258         currentDate.SetMonth(month);
1259         currentDate.SetDay(monthDaysIndex + 1); // days is index start form 0 and day start form 1.
1260         return currentDate;
1261     }
1262 
1263     uint32_t lunarYear = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1264     return LunarToSolar(GetCurrentLunarDateByMonthDaysColumn(lunarYear));
1265 }
1266 
GetCurrentLunarDateByMonthDaysColumn(uint32_t lunarYear) const1267 LunarDate DatePickerPattern::GetCurrentLunarDateByMonthDaysColumn(uint32_t lunarYear) const
1268 {
1269     LunarDate lunarResult;
1270     auto host = GetHost();
1271     CHECK_NULL_RETURN(host, lunarResult);
1272 
1273     auto children = host->GetChildren();
1274     if (children.size() <= SINGLE_CHILD_SIZE) {
1275         return lunarResult;
1276     }
1277     auto iter = children.begin();
1278     auto monthDays = (*iter);
1279     CHECK_NULL_RETURN(monthDays, lunarResult);
1280     iter++;
1281     auto year = *iter;
1282     CHECK_NULL_RETURN(year, lunarResult);
1283     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1284     auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
1285     auto stackYear = DynamicCast<FrameNode>(year);
1286     auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1287     CHECK_NULL_RETURN(monthDaysNode, lunarResult);
1288     CHECK_NULL_RETURN(yearDaysNode, lunarResult);
1289 
1290     auto monthDaysDatePickerColumnPattern = monthDaysNode->GetPattern<DatePickerColumnPattern>();
1291     auto yearDatePickerColumnPattern = yearDaysNode->GetPattern<DatePickerColumnPattern>();
1292     CHECK_NULL_RETURN(monthDaysDatePickerColumnPattern, lunarResult);
1293     CHECK_NULL_RETURN(yearDatePickerColumnPattern, lunarResult);
1294 
1295 
1296     uint32_t lunarLeapMonth = 0;
1297     bool hasLeapMonth = GetLunarLeapMonth(lunarYear, lunarLeapMonth);
1298     auto monthDaysIndex = monthDaysDatePickerColumnPattern->GetCurrentIndex();
1299     uint32_t month = 1;
1300     for (; month <= 12; ++month) { // month start from 1 to 12
1301         auto flag = hasLeapMonth && lunarLeapMonth == month;
1302         uint32_t daysInMonth = GetLunarMaxDay(lunarYear, month, flag && lunarResult.isLeapMonth);
1303         if (monthDaysIndex < daysInMonth) {
1304             break;
1305         } else {
1306             monthDaysIndex -= daysInMonth;
1307         }
1308         if (flag && !lunarResult.isLeapMonth) {
1309             --month;
1310             lunarResult.isLeapMonth = true;
1311         }
1312     }
1313     lunarResult.month = month;
1314     lunarResult.isLeapMonth = (lunarResult.month == lunarLeapMonth && hasLeapMonth);
1315     lunarResult.day = monthDaysIndex + 1; // day start form 1, index start from 0
1316     lunarResult.year = startDateLunar_.year + yearDatePickerColumnPattern->GetCurrentIndex();
1317 
1318     return lunarResult;
1319 }
1320 
AdjustLunarDate(LunarDate & date)1321 void DatePickerPattern::AdjustLunarDate(LunarDate& date)
1322 {
1323     auto host = GetHost();
1324     CHECK_NULL_VOID(host);
1325 
1326     auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
1327     CHECK_NULL_VOID(dataPickerRowLayoutProperty);
1328     startDateLunar_ = dataPickerRowLayoutProperty->GetStartDate().value_or(SolarToLunar(startDateSolar_));
1329     endDateLunar_ = dataPickerRowLayoutProperty->GetEndDate().value_or(SolarToLunar(endDateSolar_));
1330 
1331     if (LunarDateCompare(date, startDateLunar_) < 0) {
1332         date = startDateLunar_;
1333         return;
1334     }
1335     if (LunarDateCompare(date, endDateLunar_) > 0) {
1336         date = endDateLunar_;
1337     }
1338 }
1339 
LunarDateCompare(const LunarDate & left,const LunarDate & right) const1340 int DatePickerPattern::LunarDateCompare(const LunarDate& left, const LunarDate& right) const
1341 {
1342     static const int leftEqualRight = 0;   // means left = right
1343     static const int leftGreatRight = 1;   // means left > right
1344     static const int leftLessRight = -1;   // means left < right
1345     static const double addingValue = 0.5; // adding value for leap month.
1346     if (left.year > right.year) {
1347         return leftGreatRight;
1348     }
1349     if (left.year < right.year) {
1350         return leftLessRight;
1351     }
1352     double leftMonth = (left.isLeapMonth ? left.month + addingValue : left.month);
1353     double rightMonth = (right.isLeapMonth ? right.month + addingValue : right.month);
1354     if (GreatNotEqual(leftMonth, rightMonth)) {
1355         return leftGreatRight;
1356     }
1357     if (LessNotEqual(leftMonth, rightMonth)) {
1358         return leftLessRight;
1359     }
1360     if (left.day > right.day) {
1361         return leftGreatRight;
1362     }
1363     if (left.day < right.day) {
1364         return leftLessRight;
1365     }
1366     return leftEqualRight;
1367 }
1368 
LunarColumnsBuilding(const LunarDate & current)1369 void DatePickerPattern::LunarColumnsBuilding(const LunarDate& current)
1370 {
1371     RefPtr<FrameNode> yearColumn;
1372     RefPtr<FrameNode> monthColumn;
1373     RefPtr<FrameNode> dayColumn;
1374     auto host = GetHost();
1375     CHECK_NULL_VOID(host);
1376     int index = 0;
1377     for (const auto& stackChild : host->GetChildren()) {
1378         CHECK_NULL_VOID(stackChild);
1379         auto child = stackChild->GetChildAtIndex(1);
1380         CHECK_NULL_VOID(child);
1381         if (index == 0) {
1382             yearColumn = GetColumn(child->GetId());
1383         }
1384         if (index == 1) {
1385             monthColumn = GetColumn(child->GetId());
1386         }
1387         if (index == 2) {
1388             dayColumn = GetColumn(child->GetId());
1389         }
1390         index++;
1391     }
1392     CHECK_NULL_VOID(yearColumn);
1393     CHECK_NULL_VOID(monthColumn);
1394     CHECK_NULL_VOID(dayColumn);
1395 
1396     AdjustLunarStartEndDate();
1397     auto startYear = startDateLunar_.year;
1398     auto endYear = endDateLunar_.year;
1399     auto startMonth = startDateLunar_.month;
1400     auto endMonth = endDateLunar_.month;
1401     auto startDay = startDateLunar_.day;
1402     auto endDay = endDateLunar_.day;
1403     uint32_t maxDay = GetLunarMaxDay(current.year, current.month, current.isLeapMonth);
1404     if (startYear < endYear) {
1405         startMonth = 1;
1406         endMonth = 12;
1407         startDay = 1;
1408         endDay = maxDay;
1409     }
1410     if (startYear == endYear && startMonth < endMonth) {
1411         startDay = 1;
1412         endDay = maxDay;
1413     }
1414 
1415     options_[yearColumn].clear();
1416     for (uint32_t index = startYear; index <= endYear; ++index) {
1417         if (current.year == index) {
1418             auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1419             CHECK_NULL_VOID(datePickerColumnPattern);
1420             datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
1421         }
1422         options_[yearColumn].emplace_back(PickerDateF::CreateYear(index));
1423     }
1424 
1425     uint32_t lunarLeapMonth = 0;
1426     bool hasLeapMonth = GetLunarLeapMonth(current.year, lunarLeapMonth);
1427     options_[monthColumn].clear();
1428     if (startYear == endYear) {
1429         options_[monthColumn].resize(startMonth - 1, emptyPickerDate_);
1430     }
1431     // lunar's month start form startMonth to endMonth
1432     for (uint32_t index = startMonth; index <= endMonth; ++index) {
1433         if (!current.isLeapMonth && current.month == index) {
1434             auto datePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1435             CHECK_NULL_VOID(datePickerColumnPattern);
1436             datePickerColumnPattern->SetCurrentIndex(options_[monthColumn].size());
1437         }
1438         options_[monthColumn].emplace_back(PickerDateF::CreateMonth(index, true, false));
1439 
1440         if (hasLeapMonth && lunarLeapMonth == index) {
1441             if (current.isLeapMonth && current.month == index) {
1442                 auto datePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1443                 CHECK_NULL_VOID(datePickerColumnPattern);
1444                 datePickerColumnPattern->SetCurrentIndex(options_[monthColumn].size());
1445             }
1446             options_[monthColumn].emplace_back(PickerDateF::CreateMonth(index, true, true));
1447         }
1448     }
1449 
1450     options_[dayColumn].clear();
1451     if (startYear == endYear && startMonth == endMonth) {
1452         options_[dayColumn].resize(startDay - 1, emptyPickerDate_);
1453     }
1454     // lunar's day start from startDay
1455     for (uint32_t index = startDay; index <= endDay; ++index) {
1456         if (current.day == index) {
1457             auto datePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1458             CHECK_NULL_VOID(datePickerColumnPattern);
1459             datePickerColumnPattern->SetCurrentIndex(options_[dayColumn].size());
1460         }
1461         options_[dayColumn].emplace_back(PickerDateF::CreateDay(index, true));
1462     }
1463     auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1464     CHECK_NULL_VOID(yearColumnPattern);
1465     auto monthColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1466     CHECK_NULL_VOID(monthColumnPattern);
1467     auto dayColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1468     CHECK_NULL_VOID(dayColumnPattern);
1469     yearColumnPattern->SetOptions(GetOptions());
1470     monthColumnPattern->SetOptions(GetOptions());
1471     dayColumnPattern->SetOptions(GetOptions());
1472 
1473     SetShowLunar(true);
1474 }
1475 
SolarColumnsBuilding(const PickerDate & current)1476 void DatePickerPattern::SolarColumnsBuilding(const PickerDate& current)
1477 {
1478     RefPtr<FrameNode> yearColumn;
1479     RefPtr<FrameNode> monthColumn;
1480     RefPtr<FrameNode> dayColumn;
1481     auto host = GetHost();
1482     CHECK_NULL_VOID(host);
1483     int index = 0;
1484     for (const auto& stackChild : host->GetChildren()) {
1485         CHECK_NULL_VOID(stackChild);
1486         auto child = stackChild->GetChildAtIndex(1);
1487         if (index == 0) {
1488             yearColumn = GetColumn(child->GetId());
1489         }
1490         if (index == 1) {
1491             monthColumn = GetColumn(child->GetId());
1492         }
1493         if (index == 2) {
1494             dayColumn = GetColumn(child->GetId());
1495         }
1496         index++;
1497     }
1498     CHECK_NULL_VOID(yearColumn);
1499     CHECK_NULL_VOID(monthColumn);
1500     CHECK_NULL_VOID(dayColumn);
1501 
1502     AdjustSolarStartEndDate();
1503     auto startYear = startDateSolar_.GetYear();
1504     auto endYear = endDateSolar_.GetYear();
1505     auto startMonth = startDateSolar_.GetMonth();
1506     auto endMonth = endDateSolar_.GetMonth();
1507     auto startDay = startDateSolar_.GetDay();
1508     auto endDay = endDateSolar_.GetDay();
1509 
1510     uint32_t maxDay = PickerDate::GetMaxDay(current.GetYear(), current.GetMonth());
1511     if (startYear < endYear) {
1512         startMonth = 1;
1513         endMonth = 12;
1514         startDay = 1;
1515         endDay = maxDay;
1516     }
1517     if (startYear == endYear && startMonth < endMonth) {
1518         startDay = 1;
1519         endDay = maxDay;
1520     }
1521 
1522     options_[yearColumn].clear();
1523     for (uint32_t year = startYear; year <= endYear; ++year) {
1524         if (year == current.GetYear()) {
1525             auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1526             CHECK_NULL_VOID(datePickerColumnPattern);
1527             datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
1528         }
1529         options_[yearColumn].emplace_back(PickerDateF::CreateYear(year));
1530     }
1531 
1532     options_[monthColumn].clear();
1533     if (startYear == endYear) {
1534         options_[monthColumn].resize(startMonth - 1, emptyPickerDate_);
1535     }
1536     // solar's month start form 1 to 12
1537     for (uint32_t month = startMonth; month <= endMonth; month++) {
1538         if (month == current.GetMonth()) {
1539             auto datePickerColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1540             CHECK_NULL_VOID(datePickerColumnPattern);
1541             // back index = size - 1
1542             datePickerColumnPattern->SetCurrentIndex(options_[monthColumn].size());
1543         }
1544 
1545         options_[monthColumn].emplace_back(PickerDateF::CreateMonth(month, false, false));
1546     }
1547 
1548     options_[dayColumn].clear();
1549     if (startYear == endYear && startMonth == endMonth) {
1550         options_[dayColumn].resize(startDay - 1, emptyPickerDate_);
1551     }
1552     // solar's day start from 1
1553     for (uint32_t day = startDay; day <= endDay; day++) {
1554         if (day == current.GetDay()) {
1555             auto datePickerColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1556             CHECK_NULL_VOID(datePickerColumnPattern);
1557             datePickerColumnPattern->SetCurrentIndex(options_[dayColumn].size());
1558         }
1559         options_[dayColumn].emplace_back(PickerDateF::CreateDay(day, false));
1560     }
1561 
1562     auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1563     CHECK_NULL_VOID(yearColumnPattern);
1564     auto monthColumnPattern = monthColumn->GetPattern<DatePickerColumnPattern>();
1565     CHECK_NULL_VOID(monthColumnPattern);
1566     auto dayColumnPattern = dayColumn->GetPattern<DatePickerColumnPattern>();
1567     CHECK_NULL_VOID(dayColumnPattern);
1568     yearColumnPattern->SetOptions(GetOptions());
1569     monthColumnPattern->SetOptions(GetOptions());
1570     dayColumnPattern->SetOptions(GetOptions());
1571 
1572     SetShowLunar(false);
1573 }
1574 
LunarMonthDaysColumnBuilding(const LunarDate & current)1575 void DatePickerPattern::LunarMonthDaysColumnBuilding(const LunarDate& current)
1576 {
1577     RefPtr<FrameNode> monthDaysColumn;
1578     RefPtr<FrameNode> yearColumn;
1579     auto host = GetHost();
1580     CHECK_NULL_VOID(host);
1581 
1582     auto children = host->GetChildren();
1583     if (children.size() <= SINGLE_CHILD_SIZE) {
1584         return;
1585     }
1586 
1587     auto iter = children.begin();
1588     auto monthDays = (*iter);
1589     CHECK_NULL_VOID(monthDays);
1590     iter++;
1591     auto year = *iter;
1592     CHECK_NULL_VOID(year);
1593     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1594     auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
1595     auto stackYear = DynamicCast<FrameNode>(year);
1596     auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1597     CHECK_NULL_VOID(monthDaysNode);
1598     CHECK_NULL_VOID(yearDaysNode);
1599 
1600     monthDaysColumn = GetColumn(monthDaysNode->GetId());
1601     yearColumn = GetColumn(yearDaysNode->GetId());
1602     CHECK_NULL_VOID(monthDaysColumn);
1603     CHECK_NULL_VOID(yearColumn);
1604 
1605     AdjustLunarStartEndDate();
1606 
1607     auto startYear = startDateLunar_.year;
1608     auto endYear = endDateLunar_.year;
1609 
1610     options_[yearColumn].clear();
1611     for (uint32_t index = startYear; index <= endYear; ++index) {
1612         if (current.year == index) {
1613             auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1614             CHECK_NULL_VOID(datePickerColumnPattern);
1615             datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
1616         }
1617         options_[yearColumn].emplace_back(PickerDateF::CreateYear(index));
1618     }
1619 
1620     FillLunarMonthDaysOptions(current, monthDaysColumn);
1621 
1622     auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1623     auto monthDaysColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
1624     CHECK_NULL_VOID(yearColumnPattern);
1625     CHECK_NULL_VOID(monthDaysColumnPattern);
1626     yearColumnPattern->SetOptions(GetOptions());
1627     monthDaysColumnPattern->SetOptions(GetOptions());
1628 
1629     SetShowLunar(true);
1630 }
1631 
SolarMonthDaysColumnsBuilding(const PickerDate & current)1632 void DatePickerPattern::SolarMonthDaysColumnsBuilding(const PickerDate& current)
1633 {
1634     RefPtr<FrameNode> monthDaysColumn;
1635     RefPtr<FrameNode> yearColumn;
1636     auto host = GetHost();
1637     CHECK_NULL_VOID(host);
1638 
1639     auto children = host->GetChildren();
1640     if (children.size() <= SINGLE_CHILD_SIZE) {
1641         return;
1642     }
1643     auto iter = children.begin();
1644     auto monthDays = (*iter);
1645     CHECK_NULL_VOID(monthDays);
1646     iter++;
1647     auto year = *iter;
1648     CHECK_NULL_VOID(year);
1649     auto stackMonthDays = DynamicCast<FrameNode>(monthDays);
1650     auto monthDaysNode = DynamicCast<FrameNode>(stackMonthDays->GetChildAtIndex(1));
1651     auto stackYear = DynamicCast<FrameNode>(year);
1652     auto yearDaysNode = DynamicCast<FrameNode>(stackYear->GetChildAtIndex(1));
1653     monthDaysColumn = GetColumn(monthDaysNode->GetId());
1654     yearColumn = GetColumn(yearDaysNode->GetId());
1655     CHECK_NULL_VOID(monthDaysColumn);
1656     CHECK_NULL_VOID(yearColumn);
1657 
1658     AdjustSolarStartEndDate();
1659     FillSolarYearOptions(current, yearColumn);
1660 
1661     options_[monthDaysColumn].clear();
1662     for (uint32_t index = MIN_MONTH; index <= MAX_MONTH; ++index) {
1663         uint32_t maxDay = PickerDate::GetMaxDay(current.GetYear(), index);
1664         for (uint32_t dayIndex = MIN_DAY; dayIndex <= maxDay; ++dayIndex) {
1665             if (index == current.GetMonth() && dayIndex == current.GetDay()) {
1666                 auto datePickerColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
1667                 CHECK_NULL_VOID(datePickerColumnPattern);
1668                 datePickerColumnPattern->SetCurrentIndex(options_[monthDaysColumn].size());
1669             }
1670             options_[monthDaysColumn].emplace_back(PickerDateF::CreateMonthDay(index, dayIndex, false, false));
1671         }
1672     }
1673 
1674     auto yearColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1675     auto monthDaysColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
1676     CHECK_NULL_VOID(yearColumnPattern);
1677     CHECK_NULL_VOID(monthDaysColumnPattern);
1678     yearColumnPattern->SetOptions(GetOptions());
1679     monthDaysColumnPattern->SetOptions(GetOptions());
1680 
1681     SetShowLunar(false);
1682 }
1683 
FillSolarYearOptions(const PickerDate & current,RefPtr<FrameNode> & yearColumn)1684 void DatePickerPattern::FillSolarYearOptions(const PickerDate& current, RefPtr<FrameNode>& yearColumn)
1685 {
1686     options_[yearColumn].clear();
1687     for (uint32_t year = startDateSolar_.GetYear(); year <= endDateSolar_.GetYear(); ++year) {
1688         if (year == current.GetYear()) {
1689             auto datePickerColumnPattern = yearColumn->GetPattern<DatePickerColumnPattern>();
1690             CHECK_NULL_VOID(datePickerColumnPattern);
1691             datePickerColumnPattern->SetCurrentIndex(options_[yearColumn].size());
1692         }
1693         options_[yearColumn].emplace_back(PickerDateF::CreateYear(year));
1694     }
1695 }
1696 
FillLunarMonthDaysOptions(const LunarDate & current,RefPtr<FrameNode> & monthDaysColumn)1697 void DatePickerPattern::FillLunarMonthDaysOptions(const LunarDate& current, RefPtr<FrameNode>& monthDaysColumn)
1698 {
1699     uint32_t startMonth = 1;
1700     uint32_t endMonth = 12;
1701     uint32_t startDay = 1;
1702 
1703     uint32_t lunarLeapMonth = 0;
1704     bool hasLeapMonth = GetLunarLeapMonth(current.year, lunarLeapMonth);
1705     options_[monthDaysColumn].clear();
1706 
1707     for (uint32_t index = startMonth; index <= endMonth; ++index) {
1708         uint32_t maxDay = GetLunarMaxDay(current.year, index, false);
1709         for (uint32_t dayIndex = startDay; dayIndex <= maxDay; ++dayIndex) {
1710             if (!current.isLeapMonth && current.month == index && current.day == dayIndex) {
1711                 auto datePickerColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
1712                 CHECK_NULL_VOID(datePickerColumnPattern);
1713                 datePickerColumnPattern->SetCurrentIndex(options_[monthDaysColumn].size());
1714             }
1715             options_[monthDaysColumn].emplace_back(PickerDateF::CreateMonthDay(index, dayIndex, true, false));
1716         }
1717 
1718         if (!hasLeapMonth || lunarLeapMonth != index) {
1719             continue;
1720         }
1721 
1722         maxDay = GetLunarMaxDay(current.year, index, true);
1723         for (uint32_t dayIndex = startDay; dayIndex <= maxDay; ++dayIndex) {
1724             if (current.isLeapMonth && current.month == index && current.day == dayIndex) {
1725                 auto datePickerColumnPattern = monthDaysColumn->GetPattern<DatePickerColumnPattern>();
1726                 CHECK_NULL_VOID(datePickerColumnPattern);
1727                 datePickerColumnPattern->SetCurrentIndex(options_[monthDaysColumn].size());
1728             }
1729             options_[monthDaysColumn].emplace_back(PickerDateF::CreateMonthDay(index, dayIndex, true, true));
1730         }
1731     }
1732 }
1733 
AdjustSolarStartEndDate()1734 void DatePickerPattern::AdjustSolarStartEndDate()
1735 {
1736     auto host = GetHost();
1737     CHECK_NULL_VOID(host);
1738 
1739     auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
1740     CHECK_NULL_VOID(dataPickerRowLayoutProperty);
1741     startDateSolar_ = LunarToSolar(dataPickerRowLayoutProperty->GetStartDate().value_or(SolarToLunar(startDateSolar_)));
1742     endDateSolar_ = LunarToSolar(dataPickerRowLayoutProperty->GetEndDate().value_or(SolarToLunar(endDateSolar_)));
1743 
1744     if (startDateSolar_.GetYear() > endDateSolar_.GetYear()) {
1745         startDateSolar_ = startDefaultDateSolar_;
1746         endDateSolar_ = endDefaultDateSolar_;
1747     }
1748     if (startDateSolar_.GetYear() == endDateSolar_.GetYear() && startDateSolar_.GetMonth() > endDateSolar_.GetMonth()) {
1749         startDateSolar_ = startDefaultDateSolar_;
1750         endDateSolar_ = endDefaultDateSolar_;
1751     }
1752     if (startDateSolar_.GetYear() == endDateSolar_.GetYear() &&
1753         startDateSolar_.GetMonth() == endDateSolar_.GetMonth() && startDateSolar_.GetDay() > endDateSolar_.GetDay()) {
1754         startDateSolar_ = startDefaultDateSolar_;
1755         endDateSolar_ = endDefaultDateSolar_;
1756     }
1757 }
1758 
AdjustLunarStartEndDate()1759 void DatePickerPattern::AdjustLunarStartEndDate()
1760 {
1761     auto host = GetHost();
1762     CHECK_NULL_VOID(host);
1763 
1764     auto dataPickerRowLayoutProperty = host->GetLayoutProperty<DataPickerRowLayoutProperty>();
1765     CHECK_NULL_VOID(dataPickerRowLayoutProperty);
1766     startDateLunar_ = dataPickerRowLayoutProperty->GetStartDate().value_or(SolarToLunar(startDateSolar_));
1767     endDateLunar_ = dataPickerRowLayoutProperty->GetEndDate().value_or(SolarToLunar(endDateSolar_));
1768 
1769     if (GetStartDateLunar().year > GetEndDateLunar().year) {
1770         startDateLunar_ = SolarToLunar(startDefaultDateSolar_);
1771         endDateLunar_ = SolarToLunar(endDefaultDateSolar_);
1772     }
1773     if (GetStartDateLunar().year == GetEndDateLunar().year && GetStartDateLunar().month > GetEndDateLunar().month) {
1774         startDateLunar_ = SolarToLunar(startDefaultDateSolar_);
1775         endDateLunar_ = SolarToLunar(endDefaultDateSolar_);
1776     }
1777     if (GetStartDateLunar().year == GetEndDateLunar().year && GetStartDateLunar().month == GetEndDateLunar().month &&
1778         GetStartDateLunar().day > GetEndDateLunar().day) {
1779         startDateLunar_ = SolarToLunar(startDefaultDateSolar_);
1780         endDateLunar_ = SolarToLunar(endDefaultDateSolar_);
1781     }
1782 }
1783 
GetLunarLeapMonth(uint32_t year,uint32_t & outLeapMonth) const1784 bool DatePickerPattern::GetLunarLeapMonth(uint32_t year, uint32_t& outLeapMonth) const
1785 {
1786     auto leapMonth = LunarCalculator::GetLunarLeapMonth(year);
1787     if (leapMonth <= 0) {
1788         return false;
1789     }
1790 
1791     outLeapMonth = static_cast<uint32_t>(leapMonth);
1792     return true;
1793 }
1794 
GetLunarMaxDay(uint32_t year,uint32_t month,bool isLeap) const1795 uint32_t DatePickerPattern::GetLunarMaxDay(uint32_t year, uint32_t month, bool isLeap) const
1796 {
1797     if (isLeap) {
1798         return static_cast<uint32_t>(LunarCalculator::GetLunarLeapDays(year));
1799     } else {
1800         return static_cast<uint32_t>(LunarCalculator::GetLunarMonthDays(year, month));
1801     }
1802 }
1803 
SolarToLunar(const PickerDate & date) const1804 LunarDate DatePickerPattern::SolarToLunar(const PickerDate& date) const
1805 {
1806     Date result;
1807     result.year = date.GetYear();
1808     result.month = date.GetMonth();
1809     result.day = date.GetDay();
1810     return Localization::GetInstance()->GetLunarDate(result);
1811 }
1812 
LunarToSolar(const LunarDate & date) const1813 PickerDate DatePickerPattern::LunarToSolar(const LunarDate& date) const
1814 {
1815     uint32_t days = date.day - 1; // calculate days from 1900.1.1 to this date
1816     if (date.isLeapMonth) {
1817         days += LunarCalculator::GetLunarMonthDays(date.year, date.month);
1818     } else {
1819         uint32_t leapMonth = LunarCalculator::GetLunarLeapMonth(date.year);
1820         if (leapMonth < date.month) {
1821             days += LunarCalculator::GetLunarLeapDays(date.year);
1822         }
1823     }
1824     for (uint32_t month = 1; month < date.month; ++month) { // month start from 1
1825         days += LunarCalculator::GetLunarMonthDays(date.year, month);
1826     }
1827     for (uint32_t year = 1900; year < date.year; ++year) { // year start from 1900
1828         days += LunarCalculator::GetLunarYearDays(year);
1829     }
1830     days += 30; // days from solar's 1900.1.1 to lunar's 1900.1.1 is 30
1831     PickerDate result;
1832     result.FromDays(days);
1833     return result;
1834 }
1835 
Init()1836 void DatePickerPattern::Init()
1837 {
1838     if (inited_) {
1839         return;
1840     }
1841     years_.clear();
1842     solarMonths_.clear();
1843     solarDays_.clear();
1844     lunarMonths_.clear();
1845     lunarDays_.clear();
1846     localizedMonths_ = Localization::GetInstance()->GetMonths(true);
1847 
1848     inited_ = true;
1849     Localization::GetInstance()->SetOnChange([]() { inited_ = false; });
1850 }
1851 
GetYear(uint32_t year)1852 const std::string& DatePickerPattern::GetYear(uint32_t year)
1853 {
1854     Init();
1855     if (!(1900 <= year && year <= 2100)) { // year in [1900,2100]
1856         return empty_;
1857     }
1858     auto index = year - 1900;
1859     if (years_.find(index) == years_.end()) {
1860         DateTime date;
1861         date.year = year;
1862         years_[index] = Localization::GetInstance()->FormatDateTime(date, "y");
1863     }
1864     return years_[index]; // index in [0, 200]
1865 }
1866 
GetSolarMonth(uint32_t month)1867 const std::string& DatePickerPattern::GetSolarMonth(uint32_t month)
1868 {
1869     Init();
1870     if (!(1 <= month && month <= 12)) { // solar month in [1,12]
1871         return empty_;
1872     }
1873     auto index = month - 1;
1874     if (solarMonths_.find(index) == solarMonths_.end()) {
1875         if (index < localizedMonths_.size()) {
1876             solarMonths_[index] = localizedMonths_[index];
1877         } else {
1878             DateTime date;
1879             date.month = month - 1; // W3C's month start from 0 to 11
1880             solarMonths_[index] = Localization::GetInstance()->FormatDateTime(date, "M");
1881         }
1882     }
1883     return solarMonths_[index]; // index in [0,11]
1884 }
1885 
GetSolarDay(uint32_t day)1886 const std::string& DatePickerPattern::GetSolarDay(uint32_t day)
1887 {
1888     Init();
1889     if (!(1 <= day && day <= 31)) { // solar day in [1,31]
1890         return empty_;
1891     }
1892     auto index = day - 1;
1893     if (solarDays_.find(index) == solarDays_.end()) {
1894         DateTime date;
1895         date.day = day;
1896         solarDays_[index] = Localization::GetInstance()->FormatDateTime(date, "d");
1897     }
1898     return solarDays_[index]; // index in [0,30]
1899 }
1900 
GetLunarMonth(uint32_t month,bool isLeap)1901 const std::string& DatePickerPattern::GetLunarMonth(uint32_t month, bool isLeap)
1902 {
1903     Init();
1904     uint32_t index = (isLeap ? month + 12 : month); // leap month is behind 12 index
1905     if (!(1 <= index && index <= 24)) {             // lunar month need in [1,24]
1906         return empty_;
1907     }
1908     if (lunarMonths_.find(index - 1) == lunarMonths_.end()) {
1909         lunarMonths_[index - 1] = Localization::GetInstance()->GetLunarMonth(month, isLeap);
1910     }
1911     return lunarMonths_[index - 1]; // index in [0,23]
1912 }
1913 
GetLunarDay(uint32_t day)1914 const std::string& DatePickerPattern::GetLunarDay(uint32_t day)
1915 {
1916     Init();
1917     if (!(1 <= day && day <= 30)) { // lunar day need in [1,30]
1918         return empty_;
1919     }
1920     auto index = day - 1;
1921     if (lunarDays_.find(index) == lunarDays_.end()) {
1922         lunarDays_[index] = Localization::GetInstance()->GetLunarDay(day);
1923     }
1924     return lunarDays_[index]; // index in [0,29]
1925 }
1926 
GetFormatString(PickerDateF date)1927 const std::string DatePickerPattern::GetFormatString(PickerDateF date)
1928 {
1929     if (date.year.has_value()) {
1930         return GetYear(date.year.value());
1931     }
1932 
1933     std::string monthStr;
1934     if (date.month.has_value()) {
1935         monthStr = date.lunar ? GetLunarMonth(date.month.value(), date.leap) : GetSolarMonth(date.month.value());
1936         if (!date.day.has_value()) {
1937             return monthStr;
1938         }
1939     }
1940 
1941     std::string dayStr;
1942     if (date.day.has_value()) {
1943         dayStr = date.lunar ? GetLunarDay(date.day.value()) : GetSolarDay(date.day.value());
1944         return date.month.has_value() ? (monthStr + dayStr) : dayStr;
1945     }
1946 
1947     return "";
1948 }
1949 
ToJsonValue(std::unique_ptr<JsonValue> & json) const1950 void DatePickerPattern::ToJsonValue(std::unique_ptr<JsonValue>& json) const
1951 {
1952     auto GetDateString = [](const PickerDate& pickerDate) {
1953         std::string ret;
1954         ret += std::to_string(pickerDate.GetYear());
1955         ret += "-";
1956         ret += std::to_string(pickerDate.GetMonth());
1957         ret += "-";
1958         ret += std::to_string(pickerDate.GetDay());
1959         return ret;
1960     };
1961     auto rowLayoutProperty = GetLayoutProperty<DataPickerRowLayoutProperty>();
1962     CHECK_NULL_VOID(rowLayoutProperty);
1963     auto jsonConstructor = JsonUtil::Create(true);
1964     auto isLunar = rowLayoutProperty->GetLunarValue(false);
1965     if (isLunar) {
1966         jsonConstructor->Put("start", rowLayoutProperty->GetDateStart().c_str());
1967         jsonConstructor->Put("end", rowLayoutProperty->GetDateEnd().c_str());
1968         jsonConstructor->Put("selected", rowLayoutProperty->GetDateSelected().c_str());
1969     } else {
1970         jsonConstructor->Put("start", GetDateString(startDateSolar_).c_str());
1971         jsonConstructor->Put("end", GetDateString(endDateSolar_).c_str());
1972         jsonConstructor->Put("selected", GetDateString(selectedDate_).c_str());
1973     }
1974     json->Put("constructor", jsonConstructor);
1975 }
1976 
SetFocusDisable()1977 void DatePickerPattern::SetFocusDisable()
1978 {
1979     auto host = GetHost();
1980     CHECK_NULL_VOID(host);
1981 
1982     auto focusHub = host->GetFocusHub();
1983     CHECK_NULL_VOID(focusHub);
1984 
1985     focusHub->SetFocusable(false);
1986 }
1987 
SetFocusEnable()1988 void DatePickerPattern::SetFocusEnable()
1989 {
1990     auto host = GetHost();
1991     CHECK_NULL_VOID(host);
1992 
1993     auto focusHub = host->GetFocusHub();
1994     CHECK_NULL_VOID(focusHub);
1995 
1996     focusHub->SetFocusable(true);
1997 }
1998 } // namespace OHOS::Ace::NG
1999