using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace CalendarGenerationTool
{
/// <summary>
/// ChinaDate
/// 一日有十二时辰,一时辰有四刻,一刻有三盏茶,一盏茶有两柱香
/// 一柱香有五分,一分有六弹指,一弹指有十刹那,一刹那为一念
/// </summary>
///
public static partial class ChinaDate
{
public static int MyYear { get; set; }
#region ====== 内部常量 ====================================================================================
public static readonly ChineseLunisolarCalendar _chineseDateTime = new ChineseLunisolarCalendar();
public static readonly string[] _chineseNumber = { "〇", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
public static readonly string[] _chineseMonth =
{
"正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "冬月", "腊月"
};
public static readonly string[] _chineseDay =
{
"初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十",
"十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十",
"廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"
};
public static readonly string[] _chineseWeek =
{
"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"
};
public static readonly string[] _celestialStem = { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" };
public static readonly string[] _terrestrialBranch = { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" };
public static readonly string[] _chineseZodiac = { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };
public static readonly string[] _solarTerm =
{
"小寒", "大寒", "立春", "雨水", "惊蛰", "春分",
"清明", "谷雨", "立夏", "小满", "芒种", "夏至",
"小暑", "大暑", "立秋", "处暑", "白露", "秋分",
"寒露", "霜降", "立冬", "小雪", "大雪", "冬至"
};
public static readonly int[] _solarTermInfo = {
0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989,
308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758
};
public static Hashtable Public_Holiday = new Hashtable(), Lunar_Holiday = new Hashtable();
static ChinaDate()
{
//公历节日
Public_Holiday.Add("0101", "元旦");
Public_Holiday.Add("0214", "情人节");
Public_Holiday.Add("0305", "雷锋日");
Public_Holiday.Add("0308", "妇女节");
Public_Holiday.Add("0312", "植树节");
Public_Holiday.Add("0315", "消费者权益日");
Public_Holiday.Add("0501", "劳动节");
Public_Holiday.Add("0504", "青年节");
Public_Holiday.Add("0601", "儿童节");
Public_Holiday.Add("0701", "建党节");
Public_Holiday.Add("0801", "建军节");
Public_Holiday.Add("0910", "教师节");
Public_Holiday.Add("1001", "国庆节");
Public_Holiday.Add("1224", "平安夜");
Public_Holiday.Add("1225", "圣诞节");
//农历节日
Lunar_Holiday.Add("0101", "春节");
Lunar_Holiday.Add("0115", "元宵节");
Lunar_Holiday.Add("0202", "龙头节");
Lunar_Holiday.Add("0505", "端午节");
Lunar_Holiday.Add("0707", "七夕节");
Lunar_Holiday.Add("0715", "中元节");
Lunar_Holiday.Add("0815", "中秋节");
Lunar_Holiday.Add("0909", "重阳节");
Lunar_Holiday.Add("1208", "腊八节");
Lunar_Holiday.Add("1224", "小年");
}
#endregion
//------- 获取方法(Chinese) -------
#region ====== 获取农历年份 ====================================================================================
/// <summary>
/// 获取当前日期农历年份
/// </summary>
/// <returns>当前日期农历年份</returns>
public static string GetYear()
{
return GetYear(DateTime.Now);
}
/// <summary>
/// 获取给定日期农历年份
/// </summary>
/// <param name="year">四位数字年份</param>
/// <returns>给定日期农历年份</returns>
public static string GetYear(int year)
{
return GetYear(new DateTime(year, 1, 1));
}
/// <summary>
/// 获取给定日期农历年份
/// </summary>
/// <param name="year">四位数字年份</param>
/// <param name="month">数字月份</param>
/// <returns>给定日期农历年份</returns>
public static string GetYear(int year, int month)
{
return GetYear(new DateTime(year, month, 1));
}
/// <summary>
/// 获取给定日期农历年份
/// </summary>
/// <param name="year">四位数字年份</param>
/// <param name="month">数字月份</param>
/// <param name="day">数字天</param>
/// <returns>给定日期农历年份</returns>
public static string GetYear(int year, int month, int day)
{
return GetYear(new DateTime(year, month, day));
}
// <summary>
/// 获取农历年份
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>农历年份</returns>
///
public static string GetYear(DateTime dateTime)
{
var yearArray = Array.ConvertAll(_chineseDateTime.GetYear(dateTime).ToString().ToCharArray(), x => int.Parse(x.ToString()));
var year = new StringBuilder();
foreach (var item in yearArray)
year.Append(_chineseNumber[item]);
return year.ToString();
}
#endregion
#region ====== 获取农历月份 ====================================================================================
/// <summary>
/// 获取当前日期农历月份
/// </summary>
/// <returns>当前日期农历月份</returns>
public static string GetMonth()
{
return GetMonth(DateTime.Now);
}
/// <summary>
/// 获取给定日期农历月份
/// </summary>
/// <param name="year">四位数字年份</param>
/// <param name="month">数字月份</param>
/// <returns>给定日期农历月份</returns>
public static string GetMonth(int year, int month)
{
return GetMonth(new DateTime(year, month, 1));
}
/// <summary>
/// 获取给定日期农历月份
/// </summary>
/// <param name="year">四位数字月份</param>
/// <param name="month">数字月份</param>
/// <param name="day">数字天</param>
/// <returns>给定日期农历月份</returns>
public static string GetMonth(int year, int month, int day)
{
return GetMonth(new DateTime(year, month, day));
}
/// <summary>
/// 获取农历月份
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>农历月份</returns>
public static string GetMonth(DateTime dateTime)
{
int month = _chineseDateTime.GetMonth(dateTime);
int leepMonth = _chineseDateTime.GetLeapMonth(_chineseDateTime.GetYear(dateTime));//获取闰月
if (leepMonth > 0 && leepMonth <= month) month--;
return $"{GetLeap(dateTime)}{_chineseMonth[month - 1]}";
}
#endregion
#region ====== 获取农历日期(天) ====================================================================================
/// <summary>
/// 获取当前日期农历日期(天)
/// </summary>
/// <returns>返回当前日期农历日期(天)</returns>
public static string GetDay()
{
return GetDay(DateTime.Now);
}
/// <summary>
/// 获取给定日期农历日期(天)
/// </summary>
/// <param name="year">四位数字月份</param>
/// <param name="month">数字月份</param>
/// <param name="day">数字天</param>
/// <returns>返回给定日期农历日期(天)</returns>
public static string GetDay(int year, int month, int day)
{
return GetDay(new DateTime(year, month, day));
}
/// <summary>
/// 获取给定日期农历日期(天)
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>返回农历给定日农历日期(天)</returns>
public static string GetDay(DateTime dateTime)
{
string dstr = _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1];
if (!string.IsNullOrEmpty(GetLunHoliday(dateTime)))
{
return GetLunHoliday(dateTime);
}
else if (!string.IsNullOrEmpty(GetPubHoliday(dateTime)))
{
return GetPubHoliday(dateTime);
}
else
{
return "初一".Equals(dstr) ? GetMonth(dateTime) : dstr;
}
}
//-------------------------------------------------------------------------------------------------------
/// <summary>
/// 获取当前日期农历日期(天)并输出是否是节假日
/// </summary>
/// <param name="IsHoliday">是否是节假日bool变量</param>
/// <returns>返回当前日期农历日期(天)和输出是否是节假日,IsHoliday为true:表示当前为节假日,否则则不是!</returns>
public static string GetDay(out bool IsHoliday)
{
return GetDay(DateTime.Now, out IsHoliday);
}
/// <summary>
/// 获取给定日期农历日期(天)
/// </summary>
/// <param name="year">四位数字月份</param>
/// <param name="month">数字月份</param>
/// <param name="day">数字天</param>
/// <param name="IsHoliday">是否是节假日bool变量</param>
/// <returns>返回给定日期农历日期(天)和输出是否是节假日,IsHoliday为true:表示当前为节假日,否则则不是!</returns>
public static string GetDay(int year, int month, int day, out bool IsHoliday)
{
return GetDay(new DateTime(year, month, day), out IsHoliday);
}
/// <summary>
/// 获取给定日期农历日期(天)并输出是否是节假日
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <param name="IsHoliday">是否是节假日bool变量</param>
/// <returns>返回农历给定日农历日期(天)和输出是否是节假日,IsHoliday为true:表示当前为节假日,否则则不是!</returns>
public static string GetDay(DateTime dateTime, out bool IsHoliday)
{
IsHoliday = false;
string dstr = _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1];
if (!string.IsNullOrEmpty(GetLunHoliday(dateTime)))
{
IsHoliday = true;
return GetLunHoliday(dateTime);
}
else if (!string.IsNullOrEmpty(SolarTerm(dateTime)))
{
IsHoliday = true;
return SolarTerm(dateTime);
}
else if (!string.IsNullOrEmpty(GetPubHoliday(dateTime)))
{
IsHoliday = true;
return GetPubHoliday(dateTime);
}
else
{
return "初一".Equals(dstr) ? GetMonth(dateTime) : dstr;
}
}
//-------------------------------------------------------------------------------------------------------
/// <summary>
/// 获取当前日期无节日农历日期(天)
/// </summary>
/// <returns>返回当前日期无节日农历日期(天)</returns>
public static string GetDayWithoutHoliday()
{
return GetDayWithoutHoliday(DateTime.Now);
}
/// <summary>
/// 获取给定日期无节日农历日期(天)
/// </summary>
/// <param name="year">四位数字月份</param>
/// <param name="month">数字月份</param>
/// <param name="day">数字天</param>
/// <returns>返回给定日期无节日农历日期(天)</returns>
public static string GetDayWithoutHoliday(int year, int month, int day)
{
return GetDayWithoutHoliday(new DateTime(year, month, day));
}
/// <summary>
/// 获取给定日期无节日农历日期(天)
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>返回给定日期无节日农历日期(天);如:初九</returns>
public static string GetDayWithoutHoliday(DateTime dateTime)
{
return _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1];
}
#endregion
#region ====== 获取星期(数字) ====================================================================================
/// <summary>
/// 获取当前日期星期(数字)
/// </summary>
/// <returns>以数字返回当前日期星期</returns>
public static int GetWeek()
{
return GetWeek(DateTime.Now);
}
/// <summary>
/// 获取给定日期星期(数字)
/// </summary>
/// <param name="year">四位数字月份</param>
/// <param name="month">数字月份</param>
/// <param name="day">数字天</param>
/// <returns>以数字返回给定日期星期</returns>
public static int GetWeek(int year, int month, int day)
{
return GetWeek(new DateTime(year, month, day));
}
/// <summary>
/// 获取给定日期星期(数字)
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>以数字返回返回给定日期星期</returns>
public static int GetWeek(DateTime dateTime)
{
return (int)dateTime.DayOfWeek;
}
#endregion
#region ====== 判断当前日期是否是农历闰月 =============================================================================
/// <summary>
/// 判断当前日期是否是农历闰月
/// </summary>
/// <returns>是农历闰月返回true,否则返回false</returns>
public static string GetLeap()
{
return GetLeap(DateTime.Now);
}
/// <summary>
/// 判断给定日期是否是农历闰月
/// </summary>
/// <param name="year">四位数字年份</param>
/// <param name="month">数字月份</param>
/// <returns>是农历闰月返回true,否则返回false</returns>
public static string GetLeap(int year, int month)
{
return GetLeap(new DateTime(year, month, 1));
}
/// <summary>
/// 判断给定日期是否是农历闰月
/// </summary>
/// <param name="year">四位数字月份</param>
/// <param name="month">数字月份</param>
/// <param name="day">数字天</param>
/// <returns>是农历闰月返回true,否则返回false</returns>
public static string GetLeap(int year, int month, int day)
{
return GetLeap(new DateTime(year, month, day));
}
/// <summary>
/// 判断给定日期是否是农历闰月
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>给定日期是农历闰月返回true,否则返回false</returns>
public static string GetLeap(DateTime dateTime)
{
int Year = _chineseDateTime.GetYear(dateTime), Month = _chineseDateTime.GetMonth(dateTime);
return _chineseDateTime.IsLeapMonth(Year, Month) ? true ? "闰" : "L" : "";
}
#endregion
#region ====== 判断否是公历闰年 ====================================================================================
/// <summary>
/// 判断当前日期年份是否为闰年
/// </summary>
/// <returns>返回布尔值true为闰年,反之不是</returns>
public static bool IsLeapYear()
{
return IsLeapYear(DateTime.Now);
}
/// <summary>
/// 判断指定日期年份是否为闰年
/// </summary>
/// <param name="year">DateTime对象</param>
/// <returns>返回布尔值true为闰年,反之不是</returns>
public static bool IsLeapYear(DateTime dateTime)
{
return IsLeapYear(dateTime.Year);
}
/// <summary>
/// 判断指定年份是否为闰年
/// </summary>
/// <param name="year">年份</param>
/// <returns>返回布尔值true为闰年,反之不是</returns>
public static bool IsLeapYear(int year)
{
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0 && year % 3200 != 0) || year % 172800 == 0;
}
#endregion
#region ====== 获取完整农历日期 ====================================================================================
/// <summary>
/// 获取当前日期的完整农历日期
/// </summary>
/// <returns>返回当前日期的完整农历日期,如:二〇一八年六月初九</returns>
public static string GetChinaDate()
{
return GetChinaDate(DateTime.Now);
}
/// <summary>
/// 获取按给定XXXX年【1】月【1】日的完整农历日期
/// </summary>
/// <param name="year">四位数字年份</param>
/// <returns>返回给定XXXX年【1】月【1】日的完整农历日期,如:二〇一八年【正月】【初一】</returns>
public static string GetChinaDate(int year)
{
return GetChinaDate(new DateTime(year, 1, 1));
}
/// <summary>
/// 获取按给定XXXX年XX月【1】日的完整农历日期
/// </summary>
/// <param name="year">四位数字年份</param>
/// <param name="month">数字月份</param>
/// <returns>返回给定XXXX年XX月1日的完整农历日期,如:二〇一八年六月【初一】</returns>
public static string GetChinaDate(int year, int month)
{
return GetChinaDate(new DateTime(year, month, 1));
}
/// <summary>
/// 获取按给定日期的完整农历日期
/// </summary>
/// <param name="year">四位数字年份</param>
/// <param name="month">数字月份</param>
/// <param name="day">数字天</param>
/// <returns>返回给定日期的完整农历日期,如:二〇一八年六月初九</returns>
public static string GetChinaDate(int year, int month, int day)
{
return GetChinaDate(new DateTime(year, month, day));
}
/// <summary>
/// 获取给定日期完整农历日期
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>返回给定日期农历日期,如:二〇一八年六月初九</returns>
public static string GetChinaDate(DateTime dateTime)
{
if (dateTime < _chineseDateTime.MinSupportedDateTime || dateTime > _chineseDateTime.MaxSupportedDateTime)
{
throw new ArgumentOutOfRangeException(
$"参数日期不在有效的范围内:只支持{_chineseDateTime.MinSupportedDateTime.ToShortTimeString()}到{_chineseDateTime.MaxSupportedDateTime}");
}
return $"{GetYear(dateTime)}年{GetLeap(dateTime)}{GetMonth(dateTime)}{ _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1]}";
}
#endregion
#region ====== 获取节日 ====================================================================================
/// <summary>
/// 获取给定日期公历节日
/// </summary>
/// <param name="dt">给定日期(DateTime)对象</param>
/// <returns>以字符串的形式返回给定日期公历节日</returns>
public static string GetPubHoliday(DateTime dt)
{
try
{
if (IsLeapYear(MyYear) || IsLeapYear(MyYear - 1))
Public_Holiday.Add("0404", "清明节");
else
Public_Holiday.Add("0405", "清明节");
Public_Holiday.Add(GetMumHoliday(MyYear), "母亲节");
Public_Holiday.Add(GetDadHoliday(MyYear), "父亲节");
}
catch { }
string strReturn = "";
object g = Public_Holiday[dt.Month.ToString("00") + dt.Day.ToString("00")];
if (null != g)
{
strReturn = g.ToString();
}
return strReturn;
}
/// <summary>
/// 获取农历节日
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static string GetLunHoliday(DateTime dt)
{
string strReturn = "";
int year = _chineseDateTime.GetYear(dt);
int iMonth = _chineseDateTime.GetMonth(dt);
int leapMonth = _chineseDateTime.GetLeapMonth(year);
int iDay = _chineseDateTime.GetDayOfMonth(dt);
if (_chineseDateTime.GetDayOfYear(dt) == _chineseDateTime.GetDaysInYear(year))
{
strReturn = "除夕";
}
else if (leapMonth != iMonth)
{
if (leapMonth != 0 && iMonth >= leapMonth)
{
iMonth--;
}
object n = Lunar_Holiday[iMonth.ToString("00") + iDay.ToString("00")];
if (null != n)
{
if (strReturn == "")
{
strReturn = n.ToString();
}
else
{
strReturn += " " + n.ToString();
}
}
}
return strReturn;
}
/// <summary>
/// 获取指定年份母亲节节日
/// </summary>
/// <param name="year">指定年份</param>
/// <returns>母亲节字符串:"0510"</returns>
public static string GetMumHoliday(int year)
{
int day = 14 - (GetWeek(year, 5, 1) == 0 ? 7 : GetWeek(year, 5, 1)) + 1;
return $"05{day:00}";
}
/// <summary>
/// 获取指定年份父亲节节日
/// </summary>
/// <param name="year">指定年份</param>
/// <returns>父亲节字符串:"0621"</returns>
public static string GetDadHoliday(int year)
{
int day = 21 - (GetWeek(year, 6, 1) == 0 ? 7 : GetWeek(year, 6, 1)) + 1;
return $"06{day:00}";
}
#endregion
#region ====== 获取常规(数字)日期 ====================================================================================
/// <summary>
/// 短日期(农历)
/// </summary>
/// <returns>返回农历数字日期</returns>
public static string ToShortDateString(DateTime dateTime)
{
return $"{GetYear(dateTime)}-{GetLeap(dateTime)}{GetMonth(dateTime)}-{_chineseDateTime.GetDayOfMonth(dateTime)}";
}
/// <summary>
/// 长日期(农历)
/// </summary>
/// <returns>返回农历数字日期</returns>
public static string ToLongDateString(DateTime dateTime)
{
return $"{GetYear(dateTime)}年{GetLeap(dateTime)}{GetMonth(dateTime)}月-{_chineseDateTime.GetDayOfMonth(dateTime)}日";
}
/// <summary>
/// 长日期时间(农历)
/// </summary>
/// <returns>返回农历数字日期时间</returns>
public static string ToLongDateTimeString(DateTime dateTime)
{
return $"{GetYear(dateTime)}-{GetLeap(dateTime)}{GetMonth(dateTime)}-{_chineseDateTime.GetDayOfMonth(dateTime)} {dateTime.Hour}:{dateTime.Minute}:{dateTime.Second}";
}
#endregion
#region ====== 输出中文日期、中文星期、一年中的第几周、一年中的第几天、本月的第几个星期======
/// <summary>
/// 获取当前日期的中文【年月日】日期
/// </summary>
/// <returns>返回当前日期的中文【年月日】日期;如:二〇一八年六月初九</returns>
public static string GetChineseString()
{
return GetChineseString(DateTime.Now, "yMd");
}
/// <summary>
/// 获取当前日期指定格式的中文【年月日】日期
/// </summary>
/// <param name="format">日期格式化字符串,可为"yMd"、"yM"、"y"三种</param>
/// <returns>返回当前日期指定格式的中文【年月日】日期;如:GetChineseString("yM"); 结果:二〇一八年六月</returns>
public static string GetChineseString(string format)
{
return GetChineseString(DateTime.Now, format);
}
/// <summary>
/// 获取给定日期的中文【年月日】日期
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>返回给定日期的中文【年月日】日期;如:二〇一八年六月初九</returns>
public static string GetChineseString(DateTime dateTime)
{
return GetChineseString(dateTime, "yMd");
}
/// <summary>
/// 获取给定日期指定格式的中文【年月日】日期
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <param name="format">日期格式化字符串,可为"yMd"、"yM"、"y"三种</param>
/// <returns>返回给定日期指定格式的中文【年月日】日期;如:GetChineseString(DateTime.Now, "yM"); 结果:二〇一八年六月</returns>
public static string GetChineseString(DateTime dateTime, string format)
{
var year = GetYear(dateTime);
var month = GetMonth(dateTime);
var day = GetDayWithoutHoliday(dateTime);
var date = new StringBuilder();
foreach (var item in format.ToCharArray())
{
switch (item)
{
case 'y':
date.Append($"{year}年");
break;
case 'M':
date.Append($"{month}月");
break;
case 'd':
date.Append($"{day}");
break;
default:
date.Append(item);
break;
}
}
var def = $"{year}年{month}月{day}";
var result = date.ToString();
return string.IsNullOrEmpty(result) ? def : result;
}
/// <summary>
/// 获取给定日期星期
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>返回星期几,如:星期三</returns>
public static string GetChineseWeek(DateTime dateTime) => _chineseWeek[(int)dateTime.DayOfWeek];
/// <summary>
/// 获取给定日期是一年中第几天
/// </summary>
/// <param name="date">给定日期(DateTime)对象</param>
/// <returns>返回给定日期是一年中第几天</returns>
public static int GetDayNumberOfYear(DateTime dateTime)
{
return CultureInfo.CurrentCulture.Calendar.GetDayOfYear(dateTime);
}
/// <summary>
/// 判断给定日期是本月内的第几周
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <param name="sundayStart">默认为true:一周的第一天为周日,false:一周的第一天为周一</param>
/// <returns>返回给定日期是本月内的第几周</returns>
public static int GetWeekOfMonth(DateTime dateTime, bool sundayStart = true)
{
if (dateTime.Day == 1) return 1;
else
{
//得到本月第一天是周几
int dayofweek = GetWeek(dateTime.Year, dateTime.Month, 1);
//如果不是以周日开始,需要重新计算一下dayofweek,详细风DayOfWeek枚
//如果不是以周日开始,需要重新计算一下dayofweek,详细风DayOfWeek枚举的定义
if (!sundayStart)
{
dayofweek -= 1;
if (dayofweek < 0)
dayofweek = 7;
}
//得到本月的第一周一共有几天
int startWeekDays = 7 - dayofweek;
//如果要判断的日期在第一周范围内,返回1
if (dateTime.Day <= startWeekDays)
return 1;
else
{
int aday = dateTime.Day + 7 - startWeekDays;
return aday / 7 + (aday % 7 > 0 ? 1 : 0);
}
}
}
/// <summary>
/// 获取给定日期是本年中第几个星期
/// </summary>
/// <param name="date">给定日期(DateTime)对象</param>
/// <returns>返回给定日期是本年中第几个星期</returns>
public static int GetWeekNumberOfYear(DateTime dateTime)
{
return CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);
}
#endregion
#region ====== 输助方法(天干地支)===================================================================================
//年采用的头尾法,月采用的是节令法,主流日历基本上都这种结合,如百度的日历
/// <summary>
/// 获取给定日期天干地支纪元的年
/// </summary>
/// <param name="datetime">给定日期(DateTime)对象</param>
/// <returns>返回给定日期天干地支纪元的年,如:庚子年</returns>
public static string GetEraYear(DateTime datetime)
{
var sexagenaryYear = _chineseDateTime.GetSexagenaryYear(datetime);
var stemIndex = _chineseDateTime.GetCelestialStem(sexagenaryYear) - 1;
var branchIndex = _chineseDateTime.GetTerrestrialBranch(sexagenaryYear) - 1;
return $"{_celestialStem[stemIndex]}{_terrestrialBranch[branchIndex]}";
}
/// <summary>
/// 获取给定年份的天干地支和生肖
/// </summary>
/// <param name="year">给定的年份</param>
/// <returns>返回给定年份的天干地支和生肖,如:庚子鼠</returns>
public static string GetEraYearZodiac(int year)
{
int tg = ((year - 3) % 10) - 1 < 0 ? 9 : ((year - 3) % 10) - 1;
int dz = ((year - 3) % 12) - 1 < 0 ? 11 : ((year - 3) % 12) - 1;
int sx = ((year - 3) % 12) - 1 < 0 ? 11 : ((year - 3) % 12) - 1;
return $"{_celestialStem[tg]}{_terrestrialBranch[dz]}{_chineseZodiac[sx]}";
}
/// <summary>
/// 获取给定日期天干地支纪元的月
/// </summary>
/// <param name="datetime">给定日期(DateTime)对象</param>
/// <returns>返回给定日期天干地支纪元的月,如:乙酉月</returns>
public static string GetEraMonth(DateTime datetime)
{
#region ====== 节令法 ======
int Year = datetime.Year;
var solarIndex = SolarTermFunc((x, y) => x <= y, datetime, out var dt);
solarIndex = solarIndex == -1 ? 23 : solarIndex;
var currentIndex = (int)Math.Floor(solarIndex / (decimal)2);
//天干
var solarMonth = currentIndex == 0 ? 11 : currentIndex - 1; //计算天干序(月份)
var sexagenaryYear = _chineseDateTime.GetSexagenaryYear(datetime);
var stemYear = _chineseDateTime.GetCelestialStem(sexagenaryYear) - 1;
if (solarMonth == 0) //立春时,春节前后的不同处理
{
var year = _chineseDateTime.GetYear(dt);
var month = _chineseDateTime.GetMonth(dt);
stemYear = year == Year && month != 1 ? stemYear + 1 : stemYear;
}
if (solarMonth == 11) //立春在春节后,对前一节气春节前后不同处理
{
var year = _chineseDateTime.GetYear(dt);
stemYear = year != Year ? stemYear - 1 : stemYear;
}
int stemIndex;
switch (stemYear)
{
case 0:
case 5:
stemIndex = 3;
break;
case 1:
case 6:
stemIndex = 5;
break;
case 2:
case 7:
stemIndex = 7;
break;
case 3:
case 8:
stemIndex = 9;
break;
default:
stemIndex = 1;
break;
}
//天干序
stemIndex = (stemIndex - 1 + solarMonth) % 10;
//地支序
var branchIndex = currentIndex >= 11 ? currentIndex - 11 : currentIndex + 1;
return $"{_celestialStem[stemIndex]}{_terrestrialBranch[branchIndex]}";
#endregion
#region ====== 头尾法 ======
//这里算法要容易些,原理和节令法一样,只需取农历整年整月即可。未贴上来
#endregion
}
/// <summary>
/// 获取给定日期天干地支纪元的日
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>返回给定日期天干地支纪元的日;如:丁丑日</returns>
public static string GetEraDay(DateTime dateTime)
{
var ts = dateTime - new DateTime(1901, 2, 15);
var offset = ts.Days;
var sexagenaryDay = offset % 60;
return $"{_celestialStem[sexagenaryDay % 10]}{_terrestrialBranch[sexagenaryDay % 12]}";
}
/// <summary>
/// 获取给定日期天干地支纪元的时
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>返回给定日期天干地支纪元的时,如:子时</returns>
public static string GetEraHour(DateTime dateTime)
{
var hourIndex = (int)Math.Floor((dateTime.Hour + 1) / (decimal)2);
hourIndex = hourIndex == 12 ? 0 : hourIndex;
return _terrestrialBranch[hourIndex];
}
/// <summary>
/// 获取给定日期天干地支纪元的刻
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>返回给定日期天干地支纪元的刻,如:三刻</returns>
public static string GetEraMinute(DateTime dateTime)
{
var realMinute = (dateTime.Hour % 2 == 0 ? 60 : 0) + dateTime.Minute;
return $"{_chineseNumber[(int)Math.Floor(realMinute / (decimal)30) + 1]}";
}
#endregion
#region ====== 输出天干地支生肖 ====================================================================================
/// <summary>
/// 获取当前时间天干地支纪元年月日时刻
/// </summary>
/// <returns>返回指定时间天干地支纪元年月日时刻;如:戊戌年己未月甲寅日午时二刻</returns>
public static string GetChineseEraString()
{
return GetChineseEraString(DateTime.Now);
}
/// <summary>
/// 获取以当前时间指定格式的天干地支纪元的年月日时刻
/// </summary>
/// <param name="format">支持简易参数"yMdHm",传法同中文日期</param>
/// <returns>返回当前时间指定格式的天干地支纪元的年月日时刻;GetChineseEraString("yMdHm"); 结果:庚子年乙酉月丁丑日子时三刻</returns>
public static string GetChineseEraString(string format)
{
return GetChineseEraString(DateTime.Now, format);
}
/// <summary>
/// 获取指定时间天干地支纪元的年月日时刻
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>返回指定时间天干地支纪元的年月日时刻;如:戊戌年己未月甲寅日午时二刻</returns>
public static string GetChineseEraString(DateTime dateTime)
{
return GetChineseEraString(dateTime, "yMdHm");
}
/// <summary>
/// 获取以给定时间指定格式的天干地支纪元的年月日时刻
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <param name="format">日期格式化字符串,可为"yMdHm"、"yMdH"、"yMd"、"yMd"、"yM"、"y"三种</param>
/// <returns>返回给定时间指定格式的天干地支纪元的年月日时刻;GetChineseEraString(DateTime.Now, "yMdHm"); 结果:庚子年乙酉月丁丑日子时三刻</returns>
public static string GetChineseEraString(DateTime dateTime, string format)
{
var year = GetEraYear(dateTime);
var month = GetEraMonth(dateTime);
var day = GetEraDay(dateTime);
var hour = GetEraHour(dateTime);
var minute = GetEraMinute(dateTime);
var date = new StringBuilder();
foreach (var item in format.ToCharArray())
{
switch (item)
{
case 'y':
date.Append($"{year}年");
break;
case 'M':
date.Append($"{month}月");
break;
case 'd':
date.Append($"{day}日");
break;
case 'H':
date.Append($"{hour}时");
break;
case 'm':
date.Append($"{minute}刻");
break;
default:
date.Append(item);
break;
}
}
var def = $"{year}年{month}月{day}日{hour}时";
var result = date.ToString();
return string.IsNullOrEmpty(result) ? def : result;
}
/// <summary>
/// 获取当前年份生肖
/// </summary>
public static string GetChineseZodiac()
{
return GetChineseZodiac(DateTime.Now.Year);
}
/// <summary>
/// 获取指定年份生肖
/// </summary>
public static string GetChineseZodiac(int year) => _chineseZodiac[(year - 4) % 12];
#endregion
#region ======(甲子年天干地支)===================================================================================
/// <summary>
/// 计算与指定日期对应的一甲子(60 年)中循环中的年份。
/// </summary>
/// <param name="dateTime">给定日期(DateTime)对象</param>
/// <returns>甲子循环中的一个从 1 到 60 的数字,它与 date 参数对应。</returns>
public static int GetSexagenaryYear(DateTime dateTime) => _chineseDateTime.GetSexagenaryYear(dateTime);
/// <summary>
/// 计算一甲子(60 年)循环中指定年份的天干。
/// </summary>
/// <param name="sexagenaryYear">一个从 1 到 60 的整数,用于表示甲子循环中的一年。</param>
/// <returns>当sexagenaryYear 小于 1 或大于 60时,返回一个从 1 到 12 的数字。否则返回 -1 。</returns>
public static int GetCelestialStem(int sexagenaryYear)
{
if (sexagenaryYear < 1 && sexagenaryYear > 60)
{
return -1;
}
return _chineseDateTime.GetCelestialStem(sexagenaryYear);
}
/// <summary>
/// 计算甲子 (60 年) 循环中的指定年份的地支
/// </summary>
/// <param name="sexagenaryYear">一个从 1 到 60 的整数,用于表示甲子循环中的一年。</param>
/// <returns>当sexagenaryYear 小于 1 或大于 60时,返回一个从 1 到 10 的数字。否则返回 -1 。</returns>
public static int GetTerrestrialBranch(int sexagenaryYear)
{
if (sexagenaryYear < 1 && sexagenaryYear > 60)
{
return -1;
}
return _chineseDateTime.GetTerrestrialBranch(sexagenaryYear);
}
#endregion
#region ====== 24节气 ====================================================================================
/// <summary>
/// 当前节气,没有则返回空
/// </summary>
public static string SolarTerm(DateTime dateTime)
{
var i = SolarTermFunc((x, y) => x == y, dateTime, out var dt);
return i == -1 ? "" : _solarTerm[i];
}
/// <summary>
/// 上一个节气
/// </summary>
public static string GetSolarTermPrev(DateTime dateTime)
{
var i = SolarTermFunc((x, y) => x < y, dateTime, out var dt);
return i == -1 ? "" : _solarTerm[i];
}
/// <summary>
/// 下一个节气
/// </summary>
public static string GetSolarTermNext(DateTime dateTime)
{
var i = SolarTermFunc((x, y) => x > y, dateTime, out var dt);
return i == -1 ? "" : $"{_solarTerm[i]}";
}
/// <summary>
/// 节气计算(当前年),返回指定条件的节气序及日期(公历)
/// </summary>
/// <param name="func"></param>
/// <param name="dateTime"></param>
/// <returns>-1时即没找到</returns>
public static int SolarTermFunc(Expression<Func<int, int, bool>> func, DateTime date, out DateTime dateTime)
{
var baseDateAndTime = new DateTime(1900, 1, 6, 2, 5, 0); //#1/6/1900 2:05:00 AM#
var year = date.Year;
int[] solar = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 };
var expressionType = func.Body.NodeType;
if (expressionType != ExpressionType.LessThan && expressionType != ExpressionType.LessThanOrEqual &&
expressionType != ExpressionType.GreaterThan && expressionType != ExpressionType.GreaterThanOrEqual &&
expressionType != ExpressionType.Equal)
{
throw new NotSupportedException("不受支持的操作符");
}
if (expressionType == ExpressionType.LessThan || expressionType == ExpressionType.LessThanOrEqual)
{
solar = solar.OrderByDescending(x => x).ToArray();
}
foreach (var item in solar)
{
var num = 525948.76 * (year - 1900) + _solarTermInfo[item - 1];
var newDate = baseDateAndTime.AddMinutes(num); //按分钟计算
if (func.Compile()(newDate.DayOfYear, date.DayOfYear))
{
dateTime = newDate;
return item - 1;
}
}
dateTime = _chineseDateTime.MinSupportedDateTime;
return -1;
}
#endregion
}
}