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