In the last article, we finished the basic rendering of the calendar. Next, we began to internationalize the calendar.
- Calendar, successfully completed the acquisition of lunar calendar date.
The sample code is as follows:
import { i18n } from '@kit.LocalizationKit';
@Entry
@Component
struct Index {
private scrollerForScroll: Scroller = new Scroller();
private scrollerForList: Scroller = new Scroller();
@State listPosition: number = 0; // 0 means scrolling to the top of the List, 1 means intermediate value, and 2 means scrolling to the bottom of the List.
//Design lunar calendar time
getLunarDate(year: number, month: number, day: number) {
// 1. Set Gregorian calendar date
const gregorianCalendar = i18n.getCalendar("zh-Hans", "gregory");
gregorianCalendar.set(year, month - 1, day); // 月份需减1
// 2. Convert to lunar calendar
const lunarCalendar = i18n.getCalendar("zh-Hans", "chinese");
lunarCalendar.setTime(gregorianCalendar.getTimeInMillis());
// 3. Get the lunar calendar value
const lunarYear = lunarCalendar.get("year");
const lunarMonth = lunarCalendar.get("month");
const lunarDay = lunarCalendar.get("date");
// 4. Convert to Chinese lunar calendar
const lunarMonths = ['New Year', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'Winter Moon', 'Wax Moon'];
const lunarDays = ['Lunar 1st', '2nd Lunar Month', '3rd Lunar Synchronous', '4th Lunar Synchronous', '5th Lunar Attainment', 'Lunar 6', 'Lunar 7', 'Lunar 8', 'Lunar 9', 'Lunar 10',
'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen', 'Twenty',
'Twenty-one', 'Twenty-two', 'Twenty-three', 'Twenty-four', 'Twenty-five', 'Twenty-six', 'Twenty-Twenty-Seven', 'Twenty-Eight', 'Twenty-Nine', 'Thirty'];
}
getTime(index: number = 0) {
let arr: string[] = []
const date = new Date();
const year = date.getFullYear();
const month = date.getMonth() + 1 + index;
const day = date.getDate();
const week = date.getDay();
// Example: Get the day of the week on Thursday, June 5, 2025
const targetDate = new Date(year, month - 1, 1); // Note: Months are counted from 0 (5 for June)
const dayIndex = targetDate.getDay(); // Back 4 (Thursday)
const weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday"
, "Friday", "Saturday"];
for (let i = 0; i < dayIndex; i++) {
arr.push('')
}
// Get how many days there are in a month
const days = new Date(year, month, 0).getDate();
for (let i = 1; i < days + 1; i++) {
arr.push(i + '')
}
return arr
}
aboutToAppear(): void {
this.getTime()
this.getLunarDate(2025, 6, 7)
}
build() {
Column() {
// Nav head navigation bar
Row() {
Image($r('sys.media.ohos_ic_public_arrow_left'))
.width(28)
.aspectRatio(1)
.fillColor(Color.Black)
.onClick(() => {
})
Text('Calendar')
.fontSize(18)
Column()
.width(28)
}
.padding(8)
.width('100%')
.backgroundColor('#50cccccc')
.justifyContent(FlexAlign.SpaceBetween)
// Date arrangement
Row() {
Text('Sunday')
.fontColor('#FF4A24')
Text('Monday')
Text('Tuesday')
Text('Wednesday')
Text('Thursday')
Text('Friday')
Text('Saturday')
.fontColor('#FF4A24')
}
.width('100%')
.justifyContent(FlexAlign.SpaceAround)
.padding(8)
//Scroll through the calendar
Scroll(this.scrollerForScroll) {
Column() {
CalenderComp({ arr: this.getTime(), index: 0 })
CalenderComp({ arr: this.getTime(1), index: 1 })
CalenderComp({ arr: this.getTime(2), index: 2 })
}
}
.width("100%")
.layoutWeight(1)
}
.width('100%')
.layoutWeight(1)
}
}
@Component
struct CalenderComp {
@Prop arr: string[] = []
@Prop index: number = 0
year: number = 0
month: number = 0
aboutToAppear(): void {
this.year = (new Date()).getFullYear();
this.month = (new Date()).getMonth() + 1 + this.index
}
build() {
Column({ space: 5 }) {
Text(this.year + 'year' + this.month + 'month')
.fontSize(18)
.width('100%')
.padding(8)
.textAlign(TextAlign.Center)
// dividingLine
Divider()
.color(Color.Red)
.strokeWidth(2)
.margin({ top: 1, bottom: 10 })
Grid() {
ForEach(this.arr, (item: number) => {
GridItem() {
Text(item.toString())
.fontSize(16)
.textAlign(TextAlign.Center)
}
})
}
.columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
}
}
}
(Explanation: This time the lunar calendar date conversion function has been added and internationalization support has been introduced, and the core optimization includes three aspects: First, the getLunarDate() method has been added to use @kit. LocalizationKit's calendar service, which realizes the exact conversion of the Gregorian calendar to the lunar calendar through i18n.getCalendar (supports "zh-Hans" Chinese Simplified Chinese environment); Secondly, the lunar calendar data processing process was improved - the Gregorian calendar date object was set first, then converted to the lunar calendar and the year/month/day data was extracted, and an array of Chinese names of the lunar month and date (such as "first month" and "first two days") was created. Finally, test calling the lunar calendar conversion method in the aboutToAppear lifecycle (example: June 7, 2025). Although the current implementation does not display lunar calendar data in the UI, it lays the foundation for subsequent calendar components to display lunar calendar information, while maintaining the original multi-month Gregorian calendar display function (three consecutive CalenderComp components). The introduction of the internationalization module also creates the conditions for multilingual support. )
- Calendar, the interface shows the lunar calendar.
The sample code is as follows:
import { i18n } from '@kit.LocalizationKit';
interface CalenderType {
Calendar?: string;
Lunar?: string;
}
@Entry
@Component
struct Index {
private scrollerForScroll: Scroller = new Scroller();
private scrollerForList: Scroller = new Scroller();
@State listPosition: number = 0; // 0 means scrolling to the top of the List, 1 means intermediate value, and 2 means scrolling to the bottom of the List.
//Design lunar calendar time
getLunarDate(year: number, month: number, day: number) {
// 1. Set Gregorian calendar date
const gregorianCalendar = i18n.getCalendar("zh-Hans", "gregory");
gregorianCalendar.set(year, month - 1, day); // 月份需减1
// 2. Convert to lunar calendar
const lunarCalendar = i18n.getCalendar("zh-Hans", "chinese");
lunarCalendar.setTime(gregorianCalendar.getTimeInMillis());
// 3. Get the lunar calendar value
const lunarYear = lunarCalendar.get("year");
const lunarMonth = lunarCalendar.get("month");
const lunarDay = lunarCalendar.get("date");
// 4. Convert to Chinese lunar calendar
const lunarMonths = ['New Year', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'Winter Moon', 'Wax Moon'];
const lunarDays = ['Lunar 1st', '2nd Lunar Month', '3rd Lunar Synchronous', '4th Lunar Synchronous', '5th Lunar Attainment', 'Lunar 6', 'Lunar 7', 'Lunar 8', 'Lunar 9', 'Lunar 10',
'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen', 'Twenty',
'Twenty-one', 'Twenty-two', 'Twenty-three', 'Twenty-four', 'Twenty-five', 'Twenty-six', 'Twenty-Twenty-Seven', 'Twenty-Eight', 'Twenty-Nine', 'Thirty'];
return lunarDays[lunarDay - 1]
}
getTime(index: number = 0) {
let arr: CalenderType[] = []
const date = new Date();
const year = date.getFullYear();
const month = date.getMonth() + 1 + index;
const day = date.getDate();
const week = date.getDay();
// Example: Get the day of the week on Thursday, June 5, 2025
const targetDate = new Date(year, month - 1, 1); // Note: Months are counted from 0 (5 for June)
const dayIndex = targetDate.getDay(); // Back 4 (Thursday)
const weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday"
, "Friday", "Saturday"];
for (let i = 0; i < dayIndex; i++) {
arr.push({ })
}
// Get how many days there are in a month
const days = new Date(year, month, 0).getDate();
for (let i = 1; i < days + 1; i++) {
arr.push({ Calendar: i + '', Lunar: this.getLunarDate(year, month, i) })
}
return arr
}
aboutToAppear(): void {
this.getTime()
this.getLunarDate(2025, 6, 7)
}
build() {
Column() {
// Nav head navigation bar
Row() {
Image($r('sys.media.ohos_ic_public_arrow_left'))
.width(28)
.aspectRatio(1)
.fillColor(Color.Black)
.onClick(() => {
})
Text('Calendar')
.fontSize(18)
Column()
.width(28)
}
.padding(8)
.width('100%')
.backgroundColor('#50cccccc')
.justifyContent(FlexAlign.SpaceBetween)
// Date arrangement
Row() {
Text('Sunday')
.fontColor('#FF4A24')
.layoutWeight(1)
.fontSize(12)
Text('Monday')
.layoutWeight(1)
.fontSize(12)
Text('Tuesday')
.layoutWeight(1)
.fontSize(12)
Text('Wednesday')
.layoutWeight(1)
.fontSize(12)
Text('Thursday')
.fontSize(12)
.layoutWeight(1)
Text('Friday')
.fontSize(12)
.layoutWeight(1)
Text('Saturday')
.fontSize(12)
.layoutWeight(1)
.fontColor('#FF4A24')
}
.width('100%')
.justifyContent(FlexAlign.SpaceAround)
.padding(8)
//Scroll through the calendar
Scroll(this.scrollerForScroll) {
Column() {
CalenderComp({ arr: this.getTime(), index: 0 })
CalenderComp({ arr: this.getTime(1), index: 1 })
CalenderComp({ arr: this.getTime(2), index: 2 })
}
}
.width("100%")
.layoutWeight(1)
}
.width('100%')
.layoutWeight(1)
}
}
@Component
struct CalenderComp {
@Prop arr: CalenderType[] = []
@Prop index: number = 0
year: number = 0
month: number = 0
aboutToAppear(): void {
this.year = (new Date()).getFullYear();
this.month = (new Date()).getMonth() + 1 + this.index
}
build() {
Column({ space: 5 }) {
Text(this.year + 'year' + this.month + 'month')
.fontSize(18)
.width('100%')
.padding(8)
.textAlign(TextAlign.Center)
// dividingLine
Divider()
.color(Color.Red)
.strokeWidth(2)
.margin({ top: 1, bottom: 10 })
Grid() {
ForEach(this.arr, (item: CalenderType) => {
GridItem() {
Column() {
Text(item.Calendar)
.fontSize(16)
.textAlign(TextAlign.Center)
Text(item.Lunar)
.fontSize(16)
.textAlign(TextAlign.Center)
}
}
})
}
.columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
}
}
}
(Explanation: This time, the calendar function of dual line display of Gregorian calendar and lunar calendar has been realized, and the core optimization includes four aspects: first, the CalenderType interface is introduced to define a composite data structure, including the Gregorian calendar (Calendar) and lunar calendar (Lunar) fields; Secondly, the getTime() method is reconstructed to dynamically add the corresponding lunar text (such as "the third day of the first month") for each Gregorian calendar date when generating the date array, and the blank space at the beginning of the month is occupied by an empty object. Thirdly, the calendar component is upgraded to a vertical two-line layout (Column nesting), which displays both Gregorian numbers and lunar text, maintaining the same text style (centered/16 characters); Finally, optimize the week header line - add layoutWeight(1) to all text to achieve monospace, uniform font size of 12 and keep the red logo of Sunday/Saturday. At present, the complete display of the Chinese and Western calendars is realized, and the Gregorian calendar is on the top and the lunar calendar is on the bottom in each date grid, laying the foundation for subsequent festival markers and other functions. )
Top comments (0)