using System;
using Lunar.Util;
// ReSharper disable MemberCanBePrivate.Global
namespace Lunar
{
///
/// 农历月
///
public class LunarMonth
{
///
/// 农历年
///
public int Year { get; }
///
/// 农历月:1-12,闰月为负数,如闰2月为-2
///
public int Month { get; }
///
/// 天数,大月30天,小月29天
///
public int DayCount { get; }
///
/// 初一的儒略日
///
public double FirstJulianDay { get; }
///
/// 序号
///
public int Index { get; }
///
/// 地支序号
///
public int ZhiIndex { get; }
///
/// 初始化
///
/// 农历年
/// 农历月:1-12,闰月为负数,如闰2月为-2
/// 天数
/// 初一的儒略日
/// 序号
public LunarMonth(int lunarYear, int lunarMonth, int dayCount, double firstJulianDay, int index)
{
Year = lunarYear;
Month = lunarMonth;
DayCount = dayCount;
FirstJulianDay = firstJulianDay;
Index = index;
ZhiIndex = (index - 1 + LunarUtil.BASE_MONTH_ZHI_INDEX) % 12;
}
///
/// 通过农历年月初始化
///
/// 农历年
/// 农历月:1-12,闰月为负数,如闰2月为-2
/// 农历月
public static LunarMonth FromYm(int lunarYear, int lunarMonth)
{
return LunarYear.FromYear(lunarYear).GetMonth(lunarMonth);
}
///
/// 是否闰月
///
public bool Leap => Month < 0;
///
/// 天干序号
///
public int GanIndex
{
get
{
var offset = (LunarYear.FromYear(Year).GanIndex + 1) % 5 * 2;
return (Index - 1 + offset) % 10;
}
}
///
/// 天干
///
public string Gan => LunarUtil.GAN[GanIndex + 1];
///
/// 地支
///
public string Zhi => LunarUtil.ZHI[ZhiIndex + 1];
///
/// 干支
///
public string GanZhi => $"{Gan}{Zhi}";
///
/// 喜神方位
///
public string PositionXi => LunarUtil.POSITION_XI[GanIndex + 1];
///
/// 喜神方位描述
///
public string PositionXiDesc => LunarUtil.POSITION_DESC[PositionXi];
///
/// 阳贵神方位
///
public string PositionYangGui => LunarUtil.POSITION_YANG_GUI[GanIndex + 1];
///
/// 阳贵神方位描述
///
public string PositionYangGuiDesc => LunarUtil.POSITION_DESC[PositionYangGui];
///
/// 阴贵神方位
///
public string PositionYinGui => LunarUtil.POSITION_YIN_GUI[GanIndex + 1];
///
/// 阴贵神方位描述
///
public string PositionYinGuiDesc => LunarUtil.POSITION_DESC[PositionYinGui];
///
/// 福神方位
///
public string PositionFu => GetPositionFu();
///
/// 福神方位
///
/// 流派
/// 福神方位
public string GetPositionFu(int sect = 2) {
return (1 == sect ? LunarUtil.POSITION_FU : LunarUtil.POSITION_FU_2)[GanIndex + 1];
}
///
/// 福神方位描述
///
public string PositionFuDesc => GetPositionFuDesc();
///
/// 福神方位描述
///
/// 流派
/// 方位描述
public string GetPositionFuDesc(int sect = 2) {
return LunarUtil.POSITION_DESC[GetPositionFu(sect)];
}
///
/// 财神方位
///
public string PositionCai => LunarUtil.POSITION_CAI[GanIndex + 1];
///
/// 财神方位描述
///
public string PositionCaiDesc => LunarUtil.POSITION_DESC[PositionCai];
///
/// 太岁方位,如艮
///
public string PositionTaiSui
{
get
{
string p;
var m = Math.Abs(Month);
switch (m)
{
case 1:
case 5:
case 9:
p = "艮";
break;
case 3:
case 7:
case 11:
p = "坤";
break;
case 4:
case 8:
case 12:
p = "巽";
break;
default:
p = LunarUtil.POSITION_GAN[Solar.FromJulianDay(FirstJulianDay).Lunar.MonthGanIndex];
break;
}
return p;
}
}
///
/// 太岁方位描述,如东北
///
public string PositionTaiSuiDesc => LunarUtil.POSITION_DESC[PositionTaiSui];
///
/// 九星
///
public NineStar NineStar
{
get
{
var index = LunarYear.FromYear(Year).ZhiIndex % 3;
var m = Math.Abs(Month);
var monthZhiIndex = (13 + m) % 12;
var n = 27 - (index * 3);
if (monthZhiIndex < LunarUtil.BASE_MONTH_ZHI_INDEX)
{
n -= 3;
}
var offset = (n - monthZhiIndex) % 9;
return NineStar.FromIndex(offset);
}
}
///
public override string ToString()
{
return Year + "年" + (Leap ? "闰" : "") + LunarUtil.MONTH[Math.Abs(Month)] + "月(" + DayCount + "天)";
}
///
/// 推移
///
/// 月数
/// 农历月
public LunarMonth Next(int n)
{
if (0 == n)
{
return FromYm(Year, Month);
}
if (n > 0)
{
var rest = n;
var ny = Year;
var iy = ny;
var im = Month;
var index = 0;
var months = LunarYear.FromYear(ny).Months;
while (true)
{
var size = months.Count;
for (var i = 0; i < size; i++)
{
var m = months[i];
if (m.Year != iy || m.Month != im) continue;
index = i;
break;
}
var more = size - index - 1;
if (rest < more)
{
break;
}
rest -= more;
var lastMonth = months[size - 1];
iy = lastMonth.Year;
im = lastMonth.Month;
ny++;
months = LunarYear.FromYear(ny).Months;
}
return months[index + rest];
}
else
{
var rest = -n;
var ny = Year;
var iy = ny;
var im = Month;
var index = 0;
var months = LunarYear.FromYear(ny).Months;
while (true)
{
var size = months.Count;
for (var i = 0; i < size; i++)
{
var m = months[i];
if (m.Year != iy || m.Month != im) continue;
index = i;
break;
}
if (rest <= index)
{
break;
}
rest -= index;
var firstMonth = months[0];
iy = firstMonth.Year;
im = firstMonth.Month;
ny--;
months = LunarYear.FromYear(ny).Months;
}
return months[index - rest];
}
}
}
}