//---------------------------------------------------------------------
// This file is part of the Microsoft .NET Framework SDK Code Samples.
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation. See these other
//materials for detailed information regarding Microsoft code samples.
//
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//---------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.Windows.Forms;
using System.Threading;
using System.Resources;
using System.Reflection;
using System.Security.Permissions;
[assembly: CLSCompliant(true)]
[assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum,
Assertion = true)]
namespace Microsoft.Samples.ChineseCalendarCS
{
public class ChineseLunarCalendar : System.Globalization.ChineseLunisolarCalendar
{
// Summary:
// Initializes a new instance of the
// ChineseLunarCalendar class.
public ChineseLunarCalendar()
{
}
///
/// Get the right solar term by passing one valid datetime parameter.
///
/// Datetime value
/// Chinese name of solar term
public string GetSolarTerms(DateTime selectedDate)
{
if (selectedDate > MAX_YEAR ||selectedDate
/// Get the index in solar term list by passing
///
/// Current datetime
/// Index of "LunarHolDayName"
private int GetTermIndex(DateTime time)
{
int iMonth, iDay,isFirst;
isFirst = 0;
iMonth = time.Month;
iDay = time.Day;
if (iDay<15)
{
isFirst = 1;
}
//Compare current day with real solar term day.If current date is valid solar term,
//return the according index in "LunarHolDayName" array.
if (iDay == GetTermDate(time))
{
return (iMonth) * 2 - isFirst - 1;
}
else
{
return -1;
}
}
///
/// Get term day of current month from data table.
///
/// DateTime type
/// Day of term
private int GetTermDate(DateTime time)
{
byte Offset;
int iYear, iMonth, iDay, TermDay, isFirst;
isFirst = 0;
iYear = time.Year;
iMonth = time.Month;
iDay = time.Day;
try
{
//Get the according offset in static data table.
Offset = SolarTermData[iYear - MIN_YEAR.Year][(iMonth - 1) / 2];
//According to the day of month to separate one bit to
//four pieces to indicate the right offset.
if (iMonth % 2 != 0)
{
if (iDay < 15)
{
Offset = (byte)(Offset >> 6);
isFirst = 1;
}
else
Offset = (byte)((byte)(Offset & 0x3F) >> 4);
}
else
{
if (iDay < 15)
{
Offset = (byte)((byte)(Offset & 0xC) >> 2);
isFirst = 1;
}
else
{
Offset = (byte)(Offset & 0x3);
}
}
//From baseday and offset,get the real solar term day.
if (isFirst == 1)
{
TermDay = BaseDay[(iMonth - 1) * 2] + Offset;
}
else
{
TermDay = BaseDay[(iMonth - 1) * 2 + 1] + Offset;
}
}
catch (InvalidCastException)
{
throw new InvalidCastException(rmStrings.GetString("CastError"));
}
return TermDay;
}
///
/// Return the datetime of next term according to the current datetime.
///
/// Current datetime
/// The datetime of next term
public DateTime GetNextTermDate(DateTime time)
{
if (time>MAX_YEAR||timenew DateTime(2020,12,21))
{
return BLANK_YEAR; //Return the invalid datetime
}
int CurrentTermDay, iDay;
iDay = time.Day;
CurrentTermDay = GetTermDate(time);
if (iDay < CurrentTermDay)
{
return time.AddDays(CurrentTermDay - iDay);
}
else
{
if (iDay>15)
{
//Cacluate the next term of next month.
DateTime nextMonthTermDate = new DateTime(time.Year, time.Month,
GetTermDate(time.AddDays(14)));
return nextMonthTermDate.AddMonths(1);
}
else
{
return new DateTime(time.Year, time.Month,
GetTermDate(time.AddDays(15)));
}
}
}
///
/// Get the Chinese Sexagenay Year name.
/// Lunisolar calendars for other East Asian regions with similar functionality
/// are also available and this sample can be adapted for them.
/// Please check the documentation or local websites for more information.
///
/// DateTime value
/// Sexagenary Year name
public string GetChineseSexagenaryYear(DateTime time)
{
int intSexagenary = base.GetSexagenaryYear(time);
int indexOfCelestial = base.GetCelestialStem(intSexagenary);
int indexOfTerrestrial = base.GetTerrestrialBranch(intSexagenary);
string celestialStemFromRes = rmStrings.GetString("CelestialStem");
string terrestrialBranchFromRes = rmStrings.GetString("TerrestrialBranch");
string[] celestialStem = celestialStemFromRes.Split(',');
string[] terrestrialBranch = terrestrialBranchFromRes.Split(',');
return celestialStem[indexOfCelestial - 1] + terrestrialBranch[indexOfTerrestrial - 1];
}
///
/// Get the ChineseZodiac name.
///
/// DateTime value
/// Chinese Zodiac name
public string GetChineseZodiac(DateTime time)
{
int intSexagenary = base.GetSexagenaryYear(time);
int indexOfTerrestrial = base.GetTerrestrialBranch(intSexagenary);
string zodiacFromRes = rmStrings.GetString("ChineseZodiac");
string[] zodiacArray = zodiacFromRes.Split(',');
return zodiacArray[indexOfTerrestrial - 1];
}
//Define the Max and Min supported date.
private readonly DateTime MAX_YEAR = new DateTime(2020, 12, 31);
private readonly DateTime MIN_YEAR = new DateTime(2000, 1, 1);
private readonly DateTime BLANK_YEAR = new DateTime(1,1,1);
//The minimum solar term day of every month,two digitals every month.
private readonly int[] BaseDay = new int[24] {
5,19,//1
3,18,//2
5,20,//3
4,19,//4
5,20,//5
5,20,//6
6,22,//7
7,22,//8
7,22,//9
7,22,//10
7,21,//11
6,21 //12
};
//Manager to manage the local string resources.
private ResourceManager rmStrings = new ResourceManager("ChineseLunarCalendarCS.Strings", Assembly.GetExecutingAssembly());
//Stored 21X6 size matrix to record solar term offset every month from 2000-1-1 to 2020-12-31
//Every bit represents two months or four solar terms offsets.
private readonly byte[][] SolarTermData = {
new byte[]{0x65,0x01,0x11,0x41,0x15,0x14},
new byte[]{0x14,0x05,0x11,0x51,0x15,0x15},
new byte[]{0x15,0x55,0x55,0x55,0x55,0x15},
new byte[]{0x55,0x55,0x56,0x55,0x5A,0x65},
new byte[]{0x65,0x01,0x11,0x41,0x15,0x14},
new byte[]{0x14,0x05,0x11,0x51,0x15,0x15},
new byte[]{0x15,0x55,0x15,0x51,0x55,0x15},
new byte[]{0x55,0x55,0x56,0x55,0x5A,0x65},
new byte[]{0x65,0x01,0x11,0x41,0x05,0x14},
new byte[]{0x14,0x01,0x11,0x51,0x15,0x15},
new byte[]{0x15,0x55,0x15,0x51,0x55,0x15},
new byte[]{0x55,0x55,0x56,0x55,0x56,0x65},
new byte[]{0x65,0x01,0x01,0x41,0x05,0x14},
new byte[]{0x14,0x01,0x11,0x41,0x15,0x15},
new byte[]{0x15,0x55,0x15,0x51,0x55,0x15},
new byte[]{0x55,0x55,0x56,0x55,0x56,0x55},
new byte[]{0x55,0x00,0x01,0x41,0x05,0x14},
new byte[]{0x10,0x01,0x11,0x41,0x15,0x15},
new byte[]{0x15,0x15,0x15,0x51,0x55,0x15},
new byte[]{0x15,0x55,0x55,0x55,0x56,0x55},
new byte[]{0x55,0x00,0x01,0x00,0x05,0x14} };
}
}