1817 lines
74 KiB
C#
1817 lines
74 KiB
C#
using System.Globalization;
|
||
using System.Collections;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using ryCommon;
|
||
|
||
/// <summary>
|
||
/// 中国农历类,最大支持公元0-9999年
|
||
/// </summary>
|
||
/// 日期:2019-02-09
|
||
/// 作者:http://www.cnblogs.com/zjfree/
|
||
public static class ChinaDate
|
||
{
|
||
/// <summary>
|
||
/// 日历类型
|
||
/// </summary>
|
||
public enum TCalendarType
|
||
{
|
||
/// <summary>
|
||
/// 无效
|
||
/// </summary>
|
||
ctinvalid,
|
||
/// <summary>
|
||
/// Julian 日历
|
||
/// </summary>
|
||
ctJulian,
|
||
/// <summary>
|
||
/// Gregorian 日历
|
||
/// </summary>
|
||
ctGregorian,
|
||
/// <summary>
|
||
/// 有效
|
||
/// </summary>
|
||
ctInvalid
|
||
}
|
||
private static ChineseLunisolarCalendar china = new ChineseLunisolarCalendar();
|
||
/// <summary>
|
||
/// 公历节日
|
||
/// </summary>
|
||
private static readonly Hashtable gHoliday = new Hashtable();
|
||
/// <summary>
|
||
/// 农历节日
|
||
/// </summary>
|
||
private static readonly Hashtable nHoliday = new Hashtable();
|
||
/// <summary>
|
||
/// 某个月第n个星期几
|
||
/// </summary>
|
||
private static readonly Hashtable wHoliday = new Hashtable();
|
||
private static readonly int[] SCnLeapNumber =
|
||
{
|
||
0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, 8,
|
||
9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 15, 15,
|
||
15, 16, 16, 16, 17, 17, 17, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21,
|
||
22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 26, 26, 26, 27, 27, 27,
|
||
28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 33, 33, 33, 34,
|
||
34, 34, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 40, 40,
|
||
40, 41, 41, 41, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 46, 46, 46,
|
||
47, 47, 47, 48, 48, 48, 49, 49, 50, 50, 50, 51, 51, 52, 52, 52, 53,
|
||
53, 53, 54, 54, 54, 55, 55, 56, 56, 56, 56, 57, 57, 57, 58, 58, 59,
|
||
59, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64, 64, 64, 65, 65,
|
||
65, 65, 66, 66, 66, 67, 67, 68, 68, 69, 69, 69, 69, 70, 71, 71, 71,
|
||
71, 71, 71, 72, 72, 73, 73, 74, 74, 74, 75, 75, 75, 75, 76, 76, 77,
|
||
77, 77, 77, 78, 79, 79, 79, 79, 79, 80, 80, 80, 81, 82, 82, 82, 83,
|
||
83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 86, 87, 87, 87, 87, 88, 88,
|
||
89, 89, 90, 90, 91, 91, 91, 92, 92, 93, 93, 94, 94, 94, 94, 95, 95,
|
||
96, 96, 96, 96, 97, 97, 98, 98, 98, 99, 99, 100, 100, 100, 101, 101,
|
||
101, 102, 102, 102, 103, 103, 104, 104, 104, 105, 105, 105, 106, 106,
|
||
106, 107, 107, 107, 108, 108, 109, 109, 109, 110, 110, 111, 111, 111,
|
||
112, 112, 112, 113, 113, 114, 114, 114, 115, 115, 116, 116, 116, 117,
|
||
117, 117, 117, 118, 118, 119, 119, 119, 120, 120, 121, 121, 121, 122,
|
||
122, 122, 123, 123, 124, 124, 124, 124, 125, 125, 126, 126, 126, 126,
|
||
127, 127, 128, 128, 129, 129, 130, 130, 130, 130, 131, 131, 132, 132,
|
||
132, 133, 133, 133, 134, 134, 135, 135, 135, 136, 136, 136, 137, 137,
|
||
137, 138, 138, 139, 139, 139, 140, 140, 141, 141, 141, 142, 142, 142,
|
||
143, 143, 143, 144, 144, 144, 145, 145, 146, 146, 146, 147, 147, 147,
|
||
148, 148, 149, 149, 149, 150, 150, 150, 151, 151, 151, 152, 152, 153,
|
||
153, 153, 154, 154, 154, 155, 155, 156, 156, 156, 157, 157, 157, 158,
|
||
158, 158, 159, 159, 160, 160, 160, 161, 161, 161, 162, 162, 163, 163,
|
||
163, 164, 164, 164, 165, 165, 165, 166, 166, 167, 167, 167, 168, 168,
|
||
168, 169, 169, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173,
|
||
174, 174, 174, 175, 175, 175, 176, 176, 177, 177, 177, 178, 178, 178,
|
||
179, 179, 179, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 184,
|
||
184, 184, 185, 185, 185, 186, 186, 186, 187, 187, 188, 188, 188, 189,
|
||
189, 189, 190, 190, 191, 191, 191, 192, 192, 192, 193, 193, 193, 194,
|
||
194, 195, 195, 195, 196, 196, 196, 197, 197, 198, 198, 198, 199, 199,
|
||
199, 200, 200, 200, 201, 201, 202, 202, 202, 203, 203, 203, 204, 204,
|
||
205, 205, 205, 206, 206, 206, 207, 207, 207, 208, 208, 209, 209, 209,
|
||
210, 210, 210, 211, 211, 212, 212, 212, 213, 213, 213, 214, 214, 214,
|
||
214, 214, 215, 215, 215, 216, 216, 216, 217, 217, 218, 218, 218, 219,
|
||
219, 219, 220, 220, 221, 221, 221, 222, 222, 222, 223, 223, 223, 224,
|
||
224, 225, 225, 225, 226, 226, 226, 227, 227, 228, 228, 228, 229, 229,
|
||
229, 230, 230, 230, 231, 231, 232, 232, 232, 233, 233, 233, 234, 234,
|
||
235, 235, 235, 236, 236, 236, 237, 237, 237, 238, 238, 239, 239, 239,
|
||
240, 240, 240, 241, 241, 242, 242, 242, 243, 243, 243, 244, 244, 244,
|
||
245, 245, 246, 246, 246, 247, 247, 247, 248, 248, 249, 249, 249, 250,
|
||
250, 250, 251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255,
|
||
255, 256, 256, 256, 257, 257, 257, 258, 258, 259, 259, 259, 260, 260,
|
||
260, 261, 261, 261, 262, 262, 263, 263, 263, 264, 264, 264, 265, 265,
|
||
266, 266, 266, 267, 267, 267, 268, 268, 268, 269, 269, 270, 270, 270,
|
||
271, 271, 271, 272, 272, 273, 273, 273, 274, 274, 274, 275, 275, 276,
|
||
276, 276, 277, 277, 277, 278, 278, 278, 279, 279, 280, 280, 280, 281,
|
||
281, 281, 282, 282, 283, 283, 283, 284, 284, 284, 285, 285, 285, 286,
|
||
286, 287, 287, 287, 288, 288, 288, 289, 289, 290, 290, 290, 291, 291,
|
||
291, 292, 292, 292, 293, 293, 294, 294, 294, 295, 295, 295, 296, 296,
|
||
297, 297, 297, 298, 298, 298, 299, 299, 299, 300, 300, 301, 301, 301,
|
||
302, 302, 302, 303, 303, 304, 304, 304, 305, 305, 305, 306, 306, 306,
|
||
307, 307, 308, 308, 308, 309, 309, 309, 310, 310, 311, 311, 312, 312,
|
||
312, 313, 313, 313, 314, 314, 315, 315, 315, 316, 316, 316, 317, 317,
|
||
317, 318, 318, 319, 319, 319, 320, 320, 320, 321, 321, 322, 322, 322,
|
||
323, 323, 323, 324, 324, 325, 325, 325, 326, 326, 326, 327, 327, 327,
|
||
328, 328, 329, 329, 329, 330, 330, 330, 331, 331, 332, 332, 332, 333,
|
||
333, 333, 334, 334, 334, 335, 335, 336, 336, 336, 337, 337, 337, 338,
|
||
338, 339, 339, 339, 340, 340, 340, 341, 341, 341, 342, 342, 343, 343,
|
||
343, 344, 344, 344, 345, 345, 346, 346, 346, 347, 347, 347, 348, 348,
|
||
348, 349, 349, 350, 350, 350, 351, 351, 351, 352, 352, 353, 353, 353,
|
||
354, 354, 354, 355, 355, 355, 356, 356, 357, 357, 357, 358, 358, 358,
|
||
359, 359, 360, 360, 360, 361, 361, 361, 362, 362, 362, 363, 363, 364,
|
||
364, 364, 365, 365, 365, 366, 366, 367, 367, 367, 368, 368, 368, 369,
|
||
369, 369, 370, 370, 371, 371, 371, 372, 372, 372, 373, 373, 374, 374,
|
||
374, 375, 375, 375, 376, 376, 376, 377, 377, 378, 378, 378, 379, 379,
|
||
379, 380, 380, 381, 381, 381, 382, 382, 382, 383, 383, 383, 384, 384,
|
||
385, 385, 385, 386, 386, 386, 387, 387, 388, 388, 388, 389, 389, 389,
|
||
390, 390, 390, 391, 391, 392, 392, 392, 393, 393, 393, 394, 394, 395,
|
||
395, 395, 396, 396, 396, 397, 397, 397, 398, 398, 399, 399, 399, 400,
|
||
400, 400, 401, 401, 402, 402, 402, 403, 403, 403, 404, 404, 404, 405,
|
||
405, 406, 406, 406, 407, 407, 407, 408, 408, 409, 409, 409, 410, 410,
|
||
410, 411, 411, 411, 412, 412, 413, 413, 413, 414, 414, 414, 415, 415,
|
||
416, 416, 416, 417, 417, 417, 418, 418, 418, 419, 419, 420, 420, 420,
|
||
421, 421, 421, 422, 422, 423, 423, 423, 424, 424, 424, 425, 425, 425,
|
||
426, 426, 427, 427, 427, 428, 428, 428, 429, 429, 430, 430, 430, 431,
|
||
431, 431, 432, 432, 432, 433, 433, 434, 434, 434, 435, 435, 435, 436,
|
||
436, 437, 437, 437, 438, 438, 438, 439, 439, 439, 440, 440, 441, 441,
|
||
441, 442, 442, 442, 443, 443, 444, 444, 444, 445, 445, 445, 446, 446,
|
||
446, 447, 447, 448, 448, 448, 449, 449, 449, 450, 450, 451, 451, 451,
|
||
452, 452, 452, 453, 453, 453, 454, 454, 455, 455, 455, 456, 456, 456,
|
||
457, 457, 458, 458, 458, 459, 459, 459, 460, 460, 460, 461, 461, 462,
|
||
462, 462, 463, 463, 463, 464, 464, 465, 465, 465, 466, 466, 466, 467,
|
||
467, 467, 468, 468, 469, 469, 469, 470, 470, 470, 471, 471, 472, 472,
|
||
472, 473, 473, 473, 474, 474, 474, 475, 475, 475, 476, 476, 477, 477,
|
||
477, 478, 478, 478, 479, 479, 480, 480, 480, 481, 481, 481, 482, 482,
|
||
482, 483, 483, 484, 484, 484, 485, 485, 485, 486, 486, 487, 487, 487,
|
||
488, 488, 488, 489, 489, 489, 490, 490, 491, 491, 491, 492, 492, 492,
|
||
493, 493, 494, 494, 494, 495, 495, 495, 496, 496, 496, 497, 497, 498,
|
||
498, 498, 499, 499, 499, 500, 500, 501, 501, 501, 502, 502, 502, 503,
|
||
503, 503, 504, 504, 505, 505, 505, 506, 506, 506, 507, 507, 508, 508,
|
||
508, 509, 509, 509, 510, 510, 510, 511, 511, 512, 512, 512, 513, 513,
|
||
513, 514, 514, 515, 515, 515, 516, 516, 516, 517, 517, 517, 518, 518,
|
||
519, 519, 519, 520, 520, 520, 521, 521, 522, 522, 522, 523, 523, 523,
|
||
524, 524, 524, 525, 525, 526, 526, 526, 527, 527, 527, 528, 528, 529,
|
||
529, 529, 530, 530, 530, 531, 531, 531, 532, 532, 533, 533, 533, 534,
|
||
534, 534, 535, 535, 536, 536, 536, 537, 537, 537, 538, 538, 538, 539,
|
||
539, 540, 540, 540, 541, 541, 541, 542, 542, 543, 543, 543, 544, 544,
|
||
544, 545, 545, 545, 546, 546, 547, 547, 547, 548, 548, 548, 549, 549,
|
||
550, 550, 550, 551, 551, 551, 552, 552, 552, 553, 553, 554, 554, 554,
|
||
555, 555, 555, 556, 556, 557, 557, 557, 558, 558, 558, 559, 559, 559,
|
||
560, 560, 561, 561, 561, 562, 562, 562, 563, 563, 563, 564, 564, 565,
|
||
565, 565, 566, 566, 566, 567, 567, 568, 568, 568, 569, 569, 569, 570,
|
||
570, 570, 571, 571, 572, 572, 572, 573, 573, 573, 574, 574, 575, 575,
|
||
575, 576, 576, 576, 577, 577, 578, 578, 578, 579, 579, 579, 580, 580,
|
||
580, 581, 581, 582, 582, 582, 583, 583, 583, 584, 584, 584, 585, 585,
|
||
586, 586, 586, 587, 587, 587, 588, 588, 589, 589, 589, 590, 590, 590,
|
||
591, 591, 591, 592, 592, 593, 593, 593, 594, 594, 594, 595, 595, 596,
|
||
596, 596, 597, 597, 597, 598, 598, 598, 599, 599, 600, 600, 600, 601,
|
||
601, 601, 602, 602, 603, 603, 603, 604, 604, 604, 605, 605, 605, 606,
|
||
606, 607, 607, 607, 608, 608, 608, 609, 609, 610, 610, 610, 611, 611,
|
||
611, 612, 612, 612, 613, 613, 614, 614, 614, 615, 615, 615, 616, 616,
|
||
617, 617, 617, 618, 618, 618, 619, 619, 619, 620, 620, 621, 621, 621,
|
||
622, 622, 622, 623, 623, 624, 624, 624, 625, 625, 625, 626, 626, 626,
|
||
627, 627, 628, 628, 628, 629, 629, 629, 630, 630, 631, 631, 631, 632,
|
||
632, 632, 633, 633, 633, 634, 634, 635, 635, 635, 636, 636, 636, 637,
|
||
637, 638, 638, 638, 639, 639, 639, 640, 640, 640, 641, 641, 642, 642,
|
||
642, 643, 643, 643, 644, 644, 645, 645, 645, 646, 646, 646, 647, 647,
|
||
647, 648, 648, 649, 649, 649, 650, 650, 650, 651, 651, 652, 652, 652,
|
||
653, 653, 653, 654, 654, 654, 655, 655, 656, 656, 656, 657, 657, 657,
|
||
658, 658, 659, 659, 659, 660, 660, 660, 661, 661, 661, 662, 662, 663,
|
||
663, 663, 664, 664, 664, 665, 665, 666, 666, 666, 667, 667, 667, 668,
|
||
668, 668, 669, 669, 670, 670, 670, 671, 671, 671, 672, 672, 673, 673,
|
||
673, 674, 674, 674, 675, 675, 675, 676, 676, 677, 677, 677, 678, 678,
|
||
678, 679, 679, 680, 680, 680, 681, 681, 681, 682, 682, 682, 683, 683,
|
||
684, 684, 684, 685, 685, 685, 686, 686, 687, 687, 687, 688, 688, 688,
|
||
689, 689, 689, 690, 690, 691, 691, 691, 692, 692, 692, 693, 693, 694,
|
||
694, 694, 695, 695, 695, 696, 696, 696, 697, 697, 698, 698, 698, 699,
|
||
699, 699, 700, 700, 701, 701, 701, 702, 702, 702, 703, 703, 703, 704,
|
||
704, 705, 705, 705, 706, 706, 706, 707, 707, 707, 708, 708, 709, 709,
|
||
709, 710, 710, 710, 711, 711, 712, 712, 712, 713, 713, 713, 714, 714,
|
||
714, 715, 715, 716, 716, 716, 717, 717, 717, 718, 718, 719, 719, 719,
|
||
720, 720, 720, 721, 721, 721, 722, 722, 723, 723, 723, 724, 724, 724,
|
||
725, 725, 726, 726, 726, 727, 727, 727, 728, 728, 728, 729, 729, 730,
|
||
730, 730, 731, 731, 731, 732, 732, 733, 733, 733, 734, 734, 734, 735,
|
||
735, 736, 736, 736, 737, 737, 737, 738, 738, 738, 739, 739, 740, 740,
|
||
740, 741, 741, 741, 742, 742, 742, 743, 743, 744, 744, 744, 745, 745,
|
||
745, 746, 746, 747, 747, 747, 748, 748, 748, 749, 749, 749, 750, 750,
|
||
751, 751, 751, 752, 752, 752, 754, 754, 755, 755, 755, 756, 756, 756,
|
||
757, 757, 757, 758, 758, 759, 759, 759, 760, 760, 760, 761, 761, 762,
|
||
762, 762, 763, 763, 763, 764, 764, 764, 765, 765, 766, 766, 766, 767,
|
||
767, 767, 768, 768, 769, 769, 769, 770, 770, 770, 771, 771, 771, 772,
|
||
772, 773, 773, 773, 774, 774, 774, 775, 775, 776, 776, 776, 777, 777,
|
||
777, 778, 778, 778, 779, 779, 780, 780, 780, 781, 781, 781, 782, 782,
|
||
783, 783, 783, 784, 784, 784, 785, 785, 785, 786, 786, 787, 787, 787,
|
||
788, 788, 788, 789, 789, 790, 790, 790, 791, 791, 791, 792, 792, 792,
|
||
793, 793, 794, 794, 794, 795, 795, 795, 796, 796, 796, 797, 797, 798,
|
||
798, 798, 799, 799, 799, 800, 800, 801, 801, 801, 802, 802, 802, 803,
|
||
803, 804, 804, 804, 805, 805, 805, 806, 806, 806, 807, 807, 808, 808,
|
||
808, 809, 809, 809, 810, 810, 810, 811, 811, 812, 812, 812, 813, 813,
|
||
813, 814, 814, 815, 815, 815, 816, 816, 816, 817, 817, 818, 818, 818,
|
||
819, 819, 819, 820, 820, 820, 821, 821, 822, 822, 822, 823, 823, 823,
|
||
824, 824, 825, 825, 825, 826, 826, 826, 827, 827, 827, 828, 828, 829,
|
||
829, 829, 830, 830, 830, 831, 831, 832, 832, 832, 833, 833, 833, 834,
|
||
834, 834, 835, 835, 836, 836, 836, 837, 837, 837, 838, 838, 839, 839,
|
||
839, 840, 840, 840, 841, 841, 841, 842, 842, 843, 843, 843, 844, 844,
|
||
844, 845, 845, 845, 846, 846, 847, 847, 847, 848, 848, 848, 849, 849,
|
||
850, 850, 850, 851, 851, 851, 852, 852, 852, 853, 853, 854, 854, 854,
|
||
855, 855, 855, 856, 856, 857, 857, 857, 858, 858, 858, 859, 859, 859,
|
||
860, 860, 861, 861, 861, 862, 862, 862, 863, 863, 864, 864, 863, 864,
|
||
864, 864, 865, 865, 865, 866, 866, 867, 867, 867, 868, 868, 868, 869,
|
||
869, 870, 870, 870, 871, 871, 871, 872, 872, 873, 873, 873, 874, 874,
|
||
874, 875, 875, 875, 876, 876, 877, 877, 877, 878, 878, 878, 879, 879,
|
||
879, 880, 880, 881, 881, 881, 882, 882, 882, 883, 883, 884, 884, 884,
|
||
885, 885, 885, 886, 886, 886, 887, 887, 888, 888, 888, 889, 889, 889,
|
||
890, 890, 891, 891, 891, 892, 892, 892, 893, 893, 893, 894, 894, 895,
|
||
895, 895, 896, 896, 896, 897, 897, 898, 898, 898, 899, 899, 899, 900,
|
||
900, 900, 901, 901, 902, 902, 902, 903, 903, 903, 904, 904, 905, 905,
|
||
905, 906, 906, 906, 907, 907, 907, 908, 908, 909, 909, 909, 910, 910,
|
||
910, 911, 911, 912, 912, 912, 913, 913, 913, 914, 914, 914, 915, 915,
|
||
916, 916, 916, 917, 917, 917, 918, 918, 919, 919, 919, 920, 920, 920,
|
||
921, 921, 921, 922, 922, 923, 923, 923, 924, 924, 924, 925, 925, 925,
|
||
926, 926, 927, 927, 927, 928, 928, 928, 929, 929, 930, 930, 930, 931,
|
||
931, 931, 932, 932, 932, 933, 933, 934, 934, 934, 935, 935, 935, 936,
|
||
936, 937, 937, 937, 938, 938, 938, 939, 939, 939, 940, 940, 941, 941,
|
||
941, 942, 942, 942, 943, 943, 944, 944, 944, 945, 945, 945, 946, 946,
|
||
946, 947, 947, 948, 948, 948, 949, 949, 949, 950, 950, 951, 951, 951,
|
||
952, 952, 952, 953, 953, 953, 954, 954, 955, 955, 955, 956, 956, 956,
|
||
957, 957, 958, 958, 958, 959, 959, 959, 960, 960, 960, 961, 961, 962,
|
||
962, 962, 963, 963, 963, 964, 964, 965, 965, 965, 966, 966, 966, 967,
|
||
967, 967, 968, 968, 969, 969, 969, 970, 970, 970, 971, 971, 971, 972,
|
||
972, 973, 973, 973, 974, 974, 974, 975, 975, 976, 976, 976, 977, 977,
|
||
977, 978, 978, 978, 979, 979, 980, 980, 980, 981, 981, 981, 982, 982,
|
||
983, 983, 983, 984, 984, 984, 985, 985, 986, 986, 986, 987, 987, 987,
|
||
988, 988, 988, 989, 989, 990, 990, 990, 991, 991, 991, 992, 992, 993,
|
||
993, 993, 994, 994, 994, 995, 995, 995, 996, 996, 997, 997, 997, 998,
|
||
998, 998, 999, 999, 1000, 1000, 1000, 1001, 1001, 1001, 1002, 1002,
|
||
1002, 1003, 1003, 1004, 1004, 1004, 1005, 1005, 1005, 1006, 1006,
|
||
1006, 1007, 1007, 1008, 1008, 1008, 1009, 1009, 1009, 1010, 1010,
|
||
1011, 1011, 1011, 1012, 1012, 1012, 1013, 1013, 1013, 1014, 1014,
|
||
1015, 1015, 1015, 1016, 1016, 1016, 1017, 1017, 1018, 1018, 1018,
|
||
1019, 1019, 1019, 1020, 1020, 1020, 1021, 1021, 1022, 1022, 1022,
|
||
1023, 1023, 1023, 1024, 1024, 1025, 1025, 1025, 1026, 1026, 1026,
|
||
1027, 1027, 1027, 1028, 1028, 1029, 1029, 1029, 1030, 1030, 1030,
|
||
1031, 1031, 1032, 1032, 1032, 1033, 1033, 1033, 1034, 1034, 1034,
|
||
1035, 1035, 1036, 1036, 1036, 1037, 1037, 1037, 1038, 1038, 1039,
|
||
1039, 1039, 1040, 1040, 1040, 1041, 1041, 1042, 1042, 1042, 1043,
|
||
1043, 1043, 1044, 1044, 1044, 1045, 1045, 1046, 1046, 1046, 1047,
|
||
1047, 1047, 1048, 1048, 1048, 1049, 1049, 1050, 1050, 1050, 1051,
|
||
1051, 1051, 1052, 1052, 1053, 1053, 1053, 1054, 1054, 1054, 1055,
|
||
1055, 1055, 1056, 1056, 1057, 1057, 1057, 1058, 1058, 1058, 1059,
|
||
1059, 1060, 1060, 1060, 1061, 1061, 1061, 1062, 1062, 1062, 1063,
|
||
1063, 1064, 1064, 1064, 1065, 1065, 1065, 1066, 1066, 1067, 1067,
|
||
1067, 1068, 1068, 1068, 1069, 1069, 1069, 1070, 1070, 1071, 1071,
|
||
1071, 1072, 1072, 1072, 1073, 1073, 1074, 1074, 1074, 1075, 1075,
|
||
1075, 1076, 1076, 1076, 1077, 1077, 1078, 1078, 1078, 1079, 1079,
|
||
1079, 1080, 1080, 1081, 1081, 1081, 1082, 1082, 1082, 1083, 1083,
|
||
1083, 1084, 1084
|
||
};
|
||
private static readonly string SCnLeapMonth =
|
||
"0c0080050010a0070030c0080050010a0070030c0080050020a0070030c0080050020a" +
|
||
"0070030c0090050020a0070030c0090050020a0060030c0060030c00900600c0c0060c" +
|
||
"00c00c00c0c000600c0c0006090303030006000c00c060c0006c00000c0c0c00600030" +
|
||
"30006c00009009c0090c00c009000300030906030030c0c00060c00090c0060600c003" +
|
||
"0060c00c003006009060030c0060060c0090900c00090c0090c00c0060300060600030" +
|
||
"30c0c00030c0060030c0090060030c0090300c0080050020a0060030c0080050020b00" +
|
||
"70030c0090050010a0070030b0090060020a0070040c0080050020a0060030c0080050" +
|
||
"020b0070030c0090050010a0070030b0090060020a0070040c0080050020a0060030c0" +
|
||
"080050020b0070030c0090050000c00900909009009090090090090900900909009009" +
|
||
"0090900900909009009009090090090900900900909009009090090090900900900909" +
|
||
"00900909009009009090090090900900900909009009090060030c0090050010a00700" +
|
||
"30b008005001090070040c0080050020a0060030c0090040010a0060030c0090050010" +
|
||
"a0070030b0080050010a008005001090050020a0060030c0080040010a0060030c0090" +
|
||
"050010a0070030b0080050010a0070030b008005001090070040c0080050020a006003" +
|
||
"0c0080040010a0060030c0090050010a0070030b008005001090070040c0080050020a" +
|
||
"0060030c0080040010a0060030c0090050010a0060030c0090050010a0070030b00800" +
|
||
"5001090070040c0080050020a0060030c0080040010a0070030b0080050010a0070040" +
|
||
"c0080050020a0060030c0080040010a0070030c0090050010a0070030b0080050020a0" +
|
||
"060030c0080040010a0060030c0090050050020a0060030c0090050010b0070030c009" +
|
||
"0050010a0070040c0080040020a0060030c0080050020a0060030c0090050010a00700" +
|
||
"30b0080040020a0060040c0090050020b0070030c00a0050010a0070030b0090050020" +
|
||
"a0070030c0080040020a0060030c0090050010a0070030c0090050030b007005001090" +
|
||
"050020a007004001090060020c0070050c0090060030b0080040020a0060030b008004" +
|
||
"0010a0060030b0080050010a0050040c0080050010a0060030c0080050010b0070030c" +
|
||
"007005001090070030b0070040020a0060030c0080040020a0070030b0090050010a00" +
|
||
"60040c0080050020a0060040c0080050010b0070030c007005001090070030c0080050" +
|
||
"020a0070030c0090050020a0070030c0090050020a0060040c0090050020a0060040c0" +
|
||
"090050010b0070030c0080050030b007004001090060020c008004002090060020a008" +
|
||
"004001090050030b0080040020a0060040b0080040c00a0060020b0070050010900600" +
|
||
"30b0070050020a0060020c008004002090070030c008005002090070040c0080040020" +
|
||
"a0060040b0090050010a0060030b0080050020a0060040c0080050010b007003001080" +
|
||
"05001090070030c0080050020a007003001090050030a0070030b0090050020a006004" +
|
||
"0c0090050030b0070040c0090050010c0070040c0080060020b00700400a090060020b" +
|
||
"007003002090060020a005004001090050030b007004001090050040c0080040c00a00" +
|
||
"60020c007005001090060030b0070050020a0060020c008004002090060030b0080040" +
|
||
"02090060030b0080040020a0060040b0080040010b0060030b0070050010a006004002" +
|
||
"0700500308006004003070050030700600400307005003080060040030700500409006" +
|
||
"0040030700500409006005002070050030a00600500307005004002060040020600500" +
|
||
"30020600400307005004090060040030700500408007005003080050040a0060050030" +
|
||
"7005004002060050030800500400206005002070050040020600500307006004002070" +
|
||
"050030800600400307005004080060040a006005003080050040020700500409006004" +
|
||
"002060050030b006005002070050030800600400307005004080060040030700500408" +
|
||
"0060040020" +
|
||
"700500409006004003070050040b006005002070050040b006005003070060040a0060" +
|
||
"0500307006004002060050030700600409006004003070050040900700500308005004" +
|
||
"0b00600500307006005001070050030800600400206005003070060040020600500307" +
|
||
"0060040a00700500308006004003070050040800600500107005004080060050020700" +
|
||
"50040a0060040020600500308006005002070050030800600400307005004080070050" +
|
||
"030800500408006005003070050040a006005003070050040a00600500207005004001" +
|
||
"0600500307006004001070050030700600408007005004070060040900600400307005" +
|
||
"0040a007005003080060040b0060050030800600500107005003080060040020700500" +
|
||
"3070060040030700500307006004003070050030800600400307005004090060050b00" +
|
||
"7005004090060050020700600408006005003070060030800600500307006003080060";
|
||
//{ * 自公元前 850 年开始的农历闰月信息 -849~2100,移植自中国日历类,2100 后罗建仁计算补充}
|
||
private static readonly string[] JQ = { "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至", "小寒", "大寒" };
|
||
private static readonly int[] MonthDays = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||
private static readonly int[] MonthDays2 = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||
|
||
static ChinaDate()
|
||
{
|
||
//公历节日
|
||
gHoliday.Add("0101", "元旦");
|
||
gHoliday.Add("0210", "气象节:1991");
|
||
gHoliday.Add("0214", "情人节");
|
||
gHoliday.Add("0303", "全国爱耳日:1999");
|
||
gHoliday.Add("0305", "雷锋日:1963");
|
||
gHoliday.Add("0308", "妇女节:1975");
|
||
gHoliday.Add("0312", "植树节:1979");
|
||
gHoliday.Add("0315", "消权日:1983");
|
||
gHoliday.Add("0322", "世界水日:1993");
|
||
gHoliday.Add("0401", "愚人节:1564");
|
||
gHoliday.Add("0422", "地球日:1970");
|
||
gHoliday.Add("0501", "劳动节:1890");
|
||
gHoliday.Add("0504", "青年节:1949");
|
||
gHoliday.Add("0512", "护士节:1912");
|
||
gHoliday.Add("0515", "家庭日:1989");
|
||
gHoliday.Add("0517", "世界电信日:1932");
|
||
gHoliday.Add("0531", "无烟日:1988");
|
||
gHoliday.Add("0601", "儿童节:1950");
|
||
gHoliday.Add("0605", "环境日:1972");
|
||
gHoliday.Add("0606", "全国爱眼日:1996");
|
||
gHoliday.Add("0608", "海洋日:2009");
|
||
gHoliday.Add("0614", "世界献血日:2005");
|
||
gHoliday.Add("0626", "禁毒日:1987");
|
||
gHoliday.Add("0701", "建党节:1921");
|
||
gHoliday.Add("0706", "国际接吻日:1991");
|
||
gHoliday.Add("0707", "七七事变:1937");
|
||
gHoliday.Add("0711", "人口日:1989");
|
||
gHoliday.Add("0801", "建军节:1933");
|
||
gHoliday.Add("0910", "教师节:1985");
|
||
gHoliday.Add("0920", "爱牙日:1989");
|
||
gHoliday.Add("0921", "和平日:2002");
|
||
gHoliday.Add("0922", "世界无车日:1998");
|
||
gHoliday.Add("0927", "世界旅游日:1979");
|
||
gHoliday.Add("0929", "心脏日:2011");
|
||
gHoliday.Add("1001", "国庆节:1949");
|
||
gHoliday.Add("1009", "世界邮政日:1969");
|
||
gHoliday.Add("1013", "保健日:1950");
|
||
gHoliday.Add("1016", "粮食日:1981");
|
||
gHoliday.Add("1028", "男性健康日:2000");
|
||
gHoliday.Add("1031", "万圣节:600");
|
||
gHoliday.Add("1111", "光棍节");
|
||
gHoliday.Add("1116", "宽容日:1996");
|
||
gHoliday.Add("1201", "艾滋病日:1988");
|
||
gHoliday.Add("1224", "平安夜");
|
||
gHoliday.Add("1225", "圣诞节");
|
||
|
||
//农历节日
|
||
nHoliday.Add("0101", "春节");
|
||
nHoliday.Add("0115", "元宵节");
|
||
nHoliday.Add("0202", "龙抬头");
|
||
nHoliday.Add("0505", "端午节");
|
||
nHoliday.Add("0624", "火把节");
|
||
nHoliday.Add("0707", "七夕");
|
||
nHoliday.Add("0715", "中元节");
|
||
nHoliday.Add("0722", "财神节");
|
||
nHoliday.Add("0815", "中秋节");
|
||
nHoliday.Add("0909", "重阳节");
|
||
nHoliday.Add("1001", "祭祖节");
|
||
nHoliday.Add("1208", "腊八节");
|
||
nHoliday.Add("1223", "小年(北方)");
|
||
nHoliday.Add("1224", "小年(南方)");
|
||
//某个月第n个星期几
|
||
wHoliday.Add("0527", "国际母亲节:1908");
|
||
wHoliday.Add("0637", "父亲节:1972");
|
||
wHoliday.Add("0907", "心脏日:2000-2010");//9月最后一个周日
|
||
wHoliday.Add("1011", "住房日:1986");
|
||
wHoliday.Add("1144", "感恩节:1941");//11月的第四个星期四
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取农历
|
||
/// </summary>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public static string GetChinaDate(DateTime dt)
|
||
{
|
||
string str = string.Format("{0} {1}{2}", GetYear(dt), GetMonth(dt), GetDay(dt));
|
||
string strJQ = GetSolarTerm(dt);
|
||
if (strJQ != "")
|
||
{
|
||
str += " (" + strJQ + ")";
|
||
}
|
||
//string strHoliday = GetHoliday(dt);
|
||
//string strChinaHoliday = GetChinaHoliday(dt);
|
||
//if (strHoliday != "")
|
||
//{
|
||
// str += " " + strHoliday;
|
||
//}
|
||
//if (strChinaHoliday != "")
|
||
//{
|
||
// str += " " + strChinaHoliday;
|
||
//}
|
||
|
||
return str;
|
||
}
|
||
/// <summary>
|
||
/// 获取农历
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static string GetChinaDate(int AYear, int AMonth, int ADay)
|
||
{
|
||
string str = string.Format("{0} {1}{2}", GetYear(AYear, AMonth, ADay), GetMonth(AYear, AMonth, ADay), GetDay(AYear, AMonth, ADay));
|
||
string strJQ = GetSolarTerm(AYear, AMonth, ADay);
|
||
if (strJQ != "")
|
||
{
|
||
str += " (" + strJQ + ")";
|
||
}
|
||
//string strHoliday = GetHoliday(dt);
|
||
//string strChinaHoliday = GetChinaHoliday(dt);
|
||
//if (strHoliday != "")
|
||
//{
|
||
// str += " " + strHoliday;
|
||
//}
|
||
//if (strChinaHoliday != "")
|
||
//{
|
||
// str += " " + strChinaHoliday;
|
||
//}
|
||
|
||
return str;
|
||
}
|
||
// 移植自中国日历类
|
||
private static int GetLeapMonth(int AYear)
|
||
{
|
||
char C = SCnLeapMonth[AYear + 849];
|
||
if (C >= 48 && C <= 57) //0-9
|
||
{ return (int)C - 48; }
|
||
else if (C >= 97 && C <= 122) //a-z
|
||
{
|
||
return 10 + (int)C - 97;
|
||
}
|
||
else { return -1; }
|
||
}
|
||
// 移植自中国日历类
|
||
private static int GetLeapNum(int AYear)
|
||
{
|
||
if (AYear < 0)
|
||
{
|
||
return SCnLeapNumber[AYear + 849];
|
||
}
|
||
else { return SCnLeapNumber[AYear - 1 + 849]; }
|
||
}
|
||
/// <summary>
|
||
/// 获得某农历年的闰月,返回 1~12 对应一月到十二月,返回 0 表示无闰月
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <returns></returns>
|
||
public static int GetLunarLeapMonth(int AYear)
|
||
{
|
||
int result = GetLeapMonth(AYear);
|
||
if (result < 0) { result = 0; }
|
||
return result;
|
||
}
|
||
/// <summary>
|
||
/// 农历搜索方向
|
||
/// </summary>
|
||
public enum TLunarSearchDirection
|
||
{
|
||
/// <summary>
|
||
/// 无效
|
||
/// </summary>
|
||
lsdInvalid,
|
||
/// <summary>
|
||
/// 向上
|
||
/// </summary>
|
||
lsdUp,
|
||
/// <summary>
|
||
/// 向下
|
||
/// </summary>
|
||
lsdDown
|
||
}
|
||
/// <summary>
|
||
/// {* 日月食类型, 无, 日食, 月全食, 月偏食 }
|
||
/// </summary>
|
||
public enum TEclipseType
|
||
{
|
||
/// <summary>
|
||
/// 无
|
||
/// </summary>
|
||
etNone,
|
||
/// <summary>
|
||
/// 日食
|
||
/// </summary>
|
||
etSolar,
|
||
/// <summary>
|
||
/// 月全食
|
||
/// </summary>
|
||
etMoonFull,
|
||
/// <summary>
|
||
/// 月偏食
|
||
/// </summary>
|
||
etMoonHalf
|
||
}
|
||
/// <summary>
|
||
/// {* 月相, 无, 朔, 望}
|
||
/// </summary>
|
||
public enum TMoonPhase
|
||
{
|
||
/// <summary>
|
||
/// 无
|
||
/// </summary>
|
||
mpNone,
|
||
/// <summary>
|
||
/// 朔
|
||
/// </summary>
|
||
mpShuo,
|
||
/// <summary>
|
||
/// 望
|
||
/// </summary>
|
||
mpWang
|
||
}
|
||
// 获得一大于零的数的小数部分
|
||
private static double GetTail(double X)
|
||
{
|
||
if (X > 0) { return X - Math.Truncate(X); }
|
||
else { return X + Math.Truncate(X); }
|
||
}
|
||
// 某角度计算函数,移植自中国日历类
|
||
private static double GetAng(double X, double T, double C1, double T0, double T2, double T3)
|
||
{
|
||
return GetTail(C1 * X) * 2 * Math.PI + T0 - T2 * T * T - T3 * T * T * T;
|
||
}
|
||
/// <summary>
|
||
/// 获得某公历年月日的农历日数和该日月相以及日月食类型和时刻
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <param name="EclipseType"></param>
|
||
/// <param name="MoonPhase"></param>
|
||
/// <param name="theTime"></param>
|
||
/// <returns></returns>
|
||
public static double GetLunarMoon(int AYear, int AMonth, int ADay, out TEclipseType EclipseType, out TMoonPhase MoonPhase, out double theTime)
|
||
{
|
||
double T = (AYear - 1899.5) / 100;
|
||
int Ms = Convert.ToInt32(Math.Floor((AYear - 1900) * 12.3685));
|
||
double Rpi = 180 / Math.PI;
|
||
double Zone = 8;
|
||
double F0 = GetAng(Ms, T, 0, 0.75933, 2.172e-4, 1.55e-7)
|
||
+ 0.53058868 * Ms - 8.37e-4 * T + Zone / 24 + 0.5;
|
||
double Fc = 0.1734 - 3.93e-4 * T;
|
||
double J0 = 693595 + 29 * Ms;
|
||
double Aa0 = GetAng(Ms, T, 0.08084821133, 359.2242 / Rpi, 0.0000333 / Rpi, 0.00000347 / Rpi);
|
||
double Ab0 = GetAng(Ms, T, 7.171366127999999e-2, 306.0253 / Rpi, -0.0107306 / Rpi, -0.00001236 / Rpi);
|
||
double Ac0 = GetAng(Ms, T, 0.08519585128, 21.2964 / Rpi, 0.0016528 / Rpi, 0.00000239 / Rpi);
|
||
EclipseType = TEclipseType.etNone;
|
||
int LunDay = -1;
|
||
double ShuoTime = 0;
|
||
int WangDay = 0;
|
||
double WangTime = 0;
|
||
double K1 = -1; double K = -1;
|
||
int StdDays = GetEquStandardDays(AYear, AMonth, ADay);
|
||
while (K <= 13)
|
||
{
|
||
double Aa = Aa0 + 0.507984293 * K;
|
||
double Ab = Ab0 + 6.73377553 * K;
|
||
double Ac = Ac0 + 6.818486628 * K;
|
||
double F1 = F0 + 1.53058868 * K + Fc * Math.Sin(Aa) - 0.4068 * Math.Sin(Ab)
|
||
+ 0.0021 * Math.Sin(2 * Aa) + 0.0161 * Math.Sin(2 * Ab) + 0.0104 * Math.Sin(2 * Ac)
|
||
- 0.0074 * Math.Sin(Aa - Ab) - 0.0051 * Math.Sin(Aa + Ab);
|
||
double J = J0 + 28 * K + F1;
|
||
int LunDay0 = StdDays - (int)Math.Floor(J);
|
||
if ((K == Math.Floor(K)) && (LunDay0 >= 0) && (LunDay0 <= 29))
|
||
{
|
||
K1 = K;
|
||
ShuoTime = GetTail(J);
|
||
LunDay = LunDay0 + 1;
|
||
}
|
||
if (K == K1 + 0.5)
|
||
{
|
||
WangTime = GetTail(J);
|
||
WangDay = (int)Math.Floor(J) - (StdDays - LunDay + 1) + 1;
|
||
}
|
||
if (((LunDay == 1) && (K == K1)) || ((LunDay == WangDay) && (K == K1 + 0.5)))
|
||
{
|
||
if (Math.Abs(Math.Sin(Ac)) <= 0.36)
|
||
{
|
||
double S = 5.19595 - 0.0048 * Math.Cos(Aa) + 0.002 * Math.Cos(2 * Aa) - 0.3283 * Math.Cos(Ab)
|
||
- 0.006 * Math.Cos(Aa + Ab) + 0.0041 * Math.Cos(Aa - Ab);
|
||
double R = 0.207 * Math.Sin(Aa) + 0.0024 * Math.Sin(2 * Aa) - 0.039 * Math.Sin(Ab)
|
||
+ 0.0115 * Math.Sin(2 * Ab) - 0.0073 * Math.Sin(Aa + Ab) - 0.0067 * Math.Sin(Aa - Ab)
|
||
+ 0.0117 * Math.Sin(2 * Ac);
|
||
double P = Math.Abs(S * Math.Sin(Ac) + R * Math.Cos(Ac));
|
||
double Q = 0.0059 + 0.0046 * Math.Cos(Ac) - 0.0182 * Math.Cos(Ab) + 0.0004 * Math.Cos(2 * Ab)
|
||
- 0.0005 * Math.Cos(Aa + Ab);
|
||
if (P - Q <= 1.5572)
|
||
{
|
||
EclipseType = TEclipseType.etSolar; // 日食
|
||
if (K != Math.Floor(K))
|
||
{
|
||
if (P + Q >= 1.0129)
|
||
{
|
||
EclipseType = TEclipseType.etMoonHalf; //月偏食
|
||
}
|
||
else
|
||
{
|
||
EclipseType = TEclipseType.etMoonFull; //月全食
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
K = K + 0.5;
|
||
}
|
||
// 1924.3.5 ~ 4.3 少一天
|
||
//if ((AYear == 1) && (((AMonth == 9) && (ADay >= 6)) || ((AMonth == 10) && (ADay <= 4))))
|
||
//{
|
||
// LunDay--;
|
||
// if (LunDay <1) { LunDay = LunDay + 30; }
|
||
//}
|
||
// 1924.3.5 ~ 4.3 少一天
|
||
if ((AYear == 1924) && (((AMonth == 3) && (ADay >= 5)) || ((AMonth == 4) && (ADay <= 3))))
|
||
{
|
||
LunDay++;
|
||
if (LunDay > 30) { LunDay = LunDay - 30; }
|
||
}
|
||
// 2018.11.7 ~ 12.6 多一天
|
||
if ((AYear == 2018) && (((AMonth == 11) && (ADay >= 7)) || ((AMonth == 12) && (ADay <= 6))))
|
||
{
|
||
LunDay--;
|
||
if (LunDay < 1) { LunDay = LunDay + 30; }
|
||
}
|
||
//2025.4.27 ~ 5.26 少一天
|
||
if ((AYear == 2025) && (((AMonth == 4) && (ADay >= 7)) || ((AMonth == 5) && (ADay <= 26))))
|
||
{
|
||
LunDay++;
|
||
if (LunDay > 30) { LunDay = LunDay - 30; }
|
||
}
|
||
double Result = LunDay;
|
||
if (LunDay == 1)// 朔日
|
||
{
|
||
MoonPhase = TMoonPhase.mpShuo;
|
||
theTime = ShuoTime;
|
||
}
|
||
else if (LunDay == WangDay)
|
||
{
|
||
MoonPhase = TMoonPhase.mpWang;
|
||
theTime = WangTime;
|
||
}
|
||
else
|
||
{
|
||
MoonPhase = TMoonPhase.mpNone;
|
||
theTime = -1;
|
||
}
|
||
return Result;
|
||
}
|
||
/// <summary>
|
||
/// 获得某公历年月日的农历月数
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static double GetLunarMonth(int AYear, int AMonth, int ADay)
|
||
{
|
||
double LunDay = GetLunarMoon(AYear, AMonth, ADay, out TEclipseType aEclipsType, out TMoonPhase aMoonPhase, out double aTime);
|
||
if (aTime != -1) { LunDay = LunDay + aTime; }
|
||
LunDay = Math.Floor(LunDay - Math.Floor(LunDay / 100) * 100);
|
||
int LeapMons = GetLeapNum(AYear);
|
||
int NMonth = (int)Math.Round((GetEquStandardDays(AYear, AMonth, ADay)
|
||
- GetEquStandardDays(-849, 1, 21) - LunDay) / 29.530588) - LeapMons;
|
||
//历史上的修改月建
|
||
if (AYear <= 240) NMonth++;
|
||
if (AYear <= 237) NMonth--;
|
||
if (AYear < 24) NMonth++;
|
||
if (AYear < 9) NMonth--;
|
||
if (AYear <= -255) NMonth++;
|
||
if (AYear <= -256) NMonth += 2;
|
||
if (AYear <= -722) NMonth++;
|
||
double Result = Math.Round(GetRemain(NMonth - 3, 12) + 1);
|
||
if ((Result == GetLeapMonth(AYear - 1)) && (AMonth == 1) && (ADay < LunDay))
|
||
{
|
||
Result = -Result; //如果 AYear - 1年末是闰月且该月接到了 AYear 年,则 AYear 年年初也是闰月
|
||
}
|
||
else if (Result == GetLeapMonth(AYear))
|
||
{
|
||
// 如果得到的月份数与当年所闰的月相同,比如1612年1月31号。
|
||
// 上面计算所得的是11月,并且1612年年底有个闰11月,这俩不能混淆
|
||
if (AMonth.IsInRange(1, 2) && (GetLeapMonth(AYear) != 12))
|
||
{
|
||
// 粗略判断,如果月份在年初,且今年闰月不是12月,就说明两个月不是一个年的,
|
||
// 所以不是闰月,修正为普通月。但这个修正可能不是太准确
|
||
|
||
// 比如1984年有闰10月,而1984.1.1的农历月为10,
|
||
// 但这是从1983年阴历接过来的,所以不是1984年的闰10月
|
||
Result = Result + 1;
|
||
}
|
||
else { Result = -Result; }
|
||
}
|
||
else
|
||
{
|
||
if (Result < GetLeapMonth(AYear) || (AMonth < Result) && (GetLeapMonth(AYear) > 0))
|
||
{
|
||
Result = Result + 1; //如果 AYear 年是闰月但当月未过闰月则前面多扣除了本年的闰月,这里应当补偿
|
||
}
|
||
Result = Math.Round(GetRemain(Result - 1, 12) + 1);
|
||
}
|
||
return Result;
|
||
}
|
||
// 小数的求余数
|
||
static double GetRemain(double X, double W)
|
||
{
|
||
return GetTail(X / W) * W;
|
||
}
|
||
/// <summary>
|
||
/// 获取阳历日期对应的农历日期
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <param name="LunarYear"></param>
|
||
/// <param name="LunarMonth"></param>
|
||
/// <param name="LunarDay"></param>
|
||
/// <param name="IsLeapMonth"></param>
|
||
/// <returns></returns>
|
||
public static bool GetLunarFromDay(int AYear, int AMonth, int ADay, out int LunarYear, out int LunarMonth, out int LunarDay, out bool IsLeapMonth)
|
||
{
|
||
bool Result = false;
|
||
LunarYear = 0;
|
||
LunarMonth = 0;
|
||
LunarDay = 0;
|
||
IsLeapMonth = false;
|
||
if ((AYear >= -849) && (AYear <= 2100))
|
||
{
|
||
LunarDay = (int)Math.Floor(GetLunarMoon(AYear, AMonth, ADay, out TEclipseType aEclipsType, out TMoonPhase aMoonPhase, out double aTime));
|
||
LunarMonth = (int)Math.Floor(GetLunarMonth(AYear, AMonth, ADay));
|
||
IsLeapMonth = LunarMonth < 0;
|
||
if (IsLeapMonth)
|
||
{ LunarMonth = -LunarMonth; }
|
||
LunarYear = AYear;
|
||
// 农历在下半年,公历在上半年,则农历应为上一年
|
||
if ((LunarMonth > 6) && (AMonth < 6))
|
||
{
|
||
LunarYear--;
|
||
}
|
||
Result = true;
|
||
}
|
||
return Result;
|
||
}
|
||
/// <summary>
|
||
/// 获得某公历年月日的农历月日和是否闰月的信息
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <param name="LunarMonth"></param>
|
||
/// <param name="LunarDay"></param>
|
||
/// <param name="IsLeapMonth"></param>
|
||
/// <returns></returns>
|
||
public static bool GetLunarMonthDayFromDay(int AYear, int AMonth, int ADay, out int LunarMonth, out int LunarDay, out bool IsLeapMonth)
|
||
{
|
||
bool Result = false;
|
||
LunarMonth = 0;
|
||
LunarDay = 0;
|
||
IsLeapMonth = false;
|
||
if ((AYear >= -849) && (AYear <= 2100))
|
||
{
|
||
LunarDay = (int)Math.Floor(GetLunarMoon(AYear, AMonth, ADay, out TEclipseType aEclipsType, out TMoonPhase aMoonPhase, out double aTime));
|
||
LunarMonth = (int)Math.Floor(GetLunarMonth(AYear, AMonth, ADay));
|
||
IsLeapMonth = LunarMonth < 0;
|
||
if (IsLeapMonth)
|
||
LunarMonth = -LunarMonth;
|
||
Result = true;
|
||
}
|
||
return Result;
|
||
}
|
||
/// <summary>
|
||
/// 获得等效标准日数对应的某公历日,倒推而来
|
||
/// </summary>
|
||
/// <param name="EquDays"></param>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
private static bool GetDayFromEquStandardDays(int EquDays, out int AYear, out int AMonth, out int ADay)
|
||
{
|
||
const int D1 = 365;
|
||
const int D4 = D1 * 4 + 1;
|
||
const int D100 = D4 * 25 - 1;
|
||
const int D400 = D100 * 4 + 1;
|
||
bool result = false;
|
||
AYear = 0; AMonth = 0; ADay = 0;
|
||
if (EquDays < 0) { return result; }// 暂不处理公元前的等效标准日
|
||
if (EquDays <= 577735)// 如果是 1582.10.4 (577735) 及之前为Julian历,需要修正
|
||
{
|
||
int Diff = EquDays / (365 * 100) - EquDays / (365 * 400);
|
||
EquDays -= 10;// Gregorian 删去的 10 天
|
||
EquDays += 12 - Diff; // 补上多闰的 12 天中多闰的部分
|
||
}
|
||
int T = EquDays;
|
||
int Y = 1;
|
||
while (T >= D400)
|
||
{
|
||
|
||
T -= D400;
|
||
Y += 400;
|
||
}
|
||
int I = T / D100;
|
||
int D = T % D100;
|
||
if (I == 4)
|
||
{
|
||
I--;
|
||
D += D100;
|
||
}
|
||
Y += I * 100;
|
||
I = D / D4;
|
||
D = D % D4;
|
||
Y += I * 4;
|
||
I = D / D1;
|
||
D = D % D1;
|
||
if (I == 4)
|
||
{
|
||
I--;
|
||
D += D1;
|
||
}
|
||
Y += I;
|
||
int[] DayTable = null;
|
||
if (GetIsLeapYear(Y)) { DayTable = MonthDays2; } else { DayTable = MonthDays; }
|
||
int M = 0;
|
||
while (true)
|
||
{
|
||
I = DayTable[M];
|
||
if (D < I) break;
|
||
D -= I;
|
||
M++;
|
||
}
|
||
AYear = Y;
|
||
AMonth = M + 1;
|
||
ADay = D + 1;
|
||
result = true;
|
||
return result;
|
||
}
|
||
/// <summary>
|
||
/// 比较两个农历日期(包括闰月信息),1 大于2返回1、1等于2返回0、1小于2返回-1
|
||
/// </summary>
|
||
/// <param name="Year1"></param>
|
||
/// <param name="Month1"></param>
|
||
/// <param name="Day1"></param>
|
||
/// <param name="IsLeap1"></param>
|
||
/// <param name="Year2"></param>
|
||
/// <param name="Month2"></param>
|
||
/// <param name="Day2"></param>
|
||
/// <param name="IsLeap2"></param>
|
||
/// <returns></returns>
|
||
public static int Compare2LunarDay(int Year1, int Month1, int Day1, bool IsLeap1, int Year2, int Month2, int Day2, bool IsLeap2)
|
||
{
|
||
if (Year1 > Year2)
|
||
{
|
||
return 1;
|
||
}
|
||
else if (Year1 == Year2)
|
||
{
|
||
if (Month1 > Month2)
|
||
{
|
||
return 1;
|
||
}
|
||
else if (Month1 == Month2)
|
||
{
|
||
if (IsLeap1 == IsLeap2)
|
||
{
|
||
if (Day1 > Day2)
|
||
{
|
||
return 1;
|
||
}
|
||
else if (Day1 == Day2)
|
||
{
|
||
return 0;
|
||
}
|
||
else { return -1; }
|
||
}
|
||
else if (IsLeap1 && !IsLeap2)
|
||
{
|
||
return 1;
|
||
}
|
||
else { return -1; }
|
||
}
|
||
else
|
||
{
|
||
return -1;
|
||
}
|
||
}
|
||
else { return -1; }
|
||
}
|
||
/// <summary>
|
||
/// 获得某农历年月日(加是否闰月)的公历年月日
|
||
/// 该函数采用反向二分法查找
|
||
/// </summary>
|
||
/// <param name="ALunarYear"></param>
|
||
/// <param name="ALunarMonth"></param>
|
||
/// <param name="ALunarDay"></param>
|
||
/// <param name="IsLeapMonth"></param>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static bool GetDayFromLunar(int ALunarYear, int ALunarMonth, int ALunarDay, bool IsLeapMonth, out int AYear, out int AMonth, out int ADay)
|
||
{
|
||
AYear = -1; AMonth = -1; ADay = 1;
|
||
bool result = false;
|
||
if (IsLeapMonth && (GetLunarLeapMonth(ALunarYear) != ALunarMonth)) { return result; } // 该年无此闰月则退出
|
||
// 初始范围为本公历年一月一日到次年十二月三十一日,这样做的前提是历史上正月初一
|
||
// 没有落到公历年年前去。如果有这样的情况,可考虑适当扩大搜索范围,比如从
|
||
// 上一公历年一月一日到次年十二月三十一日,但又可能引发下面对搜索范围判断的错
|
||
int StartYear = ALunarYear;
|
||
int StartMonth = 1;
|
||
int StartDay = 1;
|
||
int StartDays = GetEquStandardDays(StartYear, StartMonth, StartDay);
|
||
int EndYear = ALunarYear + 1;
|
||
int EndMonth = 12;
|
||
int EndDay = 31;
|
||
int EndDays = GetEquStandardDays(EndYear, EndMonth, EndDay);
|
||
bool Only2 = false;
|
||
TLunarSearchDirection Lsd = TLunarSearchDirection.lsdInvalid;
|
||
int TempYear = StartYear;
|
||
int TempLunarYear = StartYear;
|
||
int OldTempLunarMonth = 0;
|
||
int Count = 0;
|
||
while (StartDays < EndDays)
|
||
{
|
||
Count++;
|
||
if (Count > 100) { break; } // 避免陷入死循环
|
||
int InterDays = (StartDays + EndDays) / 2;
|
||
if (Only2)
|
||
{ InterDays++; }
|
||
if (EndDays - StartDays == 1)
|
||
{ Only2 = true; }
|
||
GetDayFromEquStandardDays(InterDays, out TempYear, out int TempMonth, out int TempDay);
|
||
GetLunarMonthDayFromDay(TempYear, TempMonth, TempDay, out int TempLunarMonth, out int TempLunarDay, out bool TempIsLeap);
|
||
switch (Lsd)
|
||
{
|
||
case TLunarSearchDirection.lsdUp:
|
||
// 往未来搜索时如果农历月由大变小了,说明跨了年,年份得加一
|
||
if (TempLunarMonth < OldTempLunarMonth)
|
||
TempLunarYear++;
|
||
break;
|
||
case TLunarSearchDirection.lsdDown:
|
||
// 往过去搜索时如果农历月由小变大了,说明跨了年,年份得减一
|
||
if (TempLunarMonth > OldTempLunarMonth)
|
||
TempLunarYear--;
|
||
break;
|
||
}
|
||
switch (Compare2LunarDay(TempLunarYear, TempLunarMonth, TempLunarDay, TempIsLeap,
|
||
ALunarYear, ALunarMonth, ALunarDay, IsLeapMonth))
|
||
{
|
||
case -1:
|
||
StartDays = InterDays;
|
||
Lsd = TLunarSearchDirection.lsdUp; // 往未来搜索
|
||
break;
|
||
case 0:
|
||
AYear = TempYear;
|
||
AMonth = TempMonth;
|
||
ADay = TempDay;
|
||
return true;
|
||
case 1:
|
||
EndDays = InterDays;
|
||
Lsd = TLunarSearchDirection.lsdDown; // 往过去搜索
|
||
break;
|
||
}
|
||
OldTempLunarMonth = TempLunarMonth;
|
||
}
|
||
return false;
|
||
}
|
||
/// <summary>
|
||
/// 获取农历某一个月的总天数
|
||
/// </summary>
|
||
/// <param name="ALunarYear"></param>
|
||
/// <param name="ALunarMonth"></param>
|
||
/// <param name="IsLeapMonth"></param>
|
||
/// <returns></returns>
|
||
public static int GetLunarMonthDays(int ALunarYear, int ALunarMonth, bool IsLeapMonth = false)
|
||
{
|
||
// 该年无此闰月则退出
|
||
if (IsLeapMonth && (GetLunarLeapMonth(ALunarYear) != ALunarMonth)) { return -1; }
|
||
if (!GetDayFromLunar(ALunarYear, ALunarMonth, 1, IsLeapMonth, out int AYear, out int AMonth, out int ADay)) { return -1; }
|
||
//if(ALunarYear==1 && ALunarMonth == 9) { return 29; }
|
||
int EquDay1 = GetEquStandardDays(AYear, AMonth, ADay);
|
||
bool ALeap = false;
|
||
if (GetLunarLeapMonth(ALunarYear) == ALunarMonth)
|
||
{
|
||
if (IsLeapMonth)// 如果输入就是闰月,则后推一个月
|
||
{
|
||
ALunarMonth++;
|
||
if (ALunarMonth > 12)
|
||
{ ALunarMonth -= 12; ALunarYear++; }
|
||
}
|
||
else { ALeap = true; }
|
||
}
|
||
else
|
||
{
|
||
ALunarMonth++;
|
||
if (ALunarMonth > 12)
|
||
{
|
||
ALunarMonth -= 12; ALunarYear++;
|
||
}
|
||
}
|
||
if (!GetDayFromLunar(ALunarYear, ALunarMonth, 1, ALeap, out AYear, out AMonth, out ADay)) { return -1; }
|
||
int EquDay2 = GetEquStandardDays(AYear, AMonth, ADay);
|
||
return EquDay2 - EquDay1;
|
||
}
|
||
/// <summary>
|
||
/// 获取农历年份,范围约1901-2101年
|
||
/// </summary>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public static string GetYear(DateTime dt)
|
||
{
|
||
return GetYear(dt.Year,dt.Month,dt.Day);
|
||
}
|
||
/// <summary>
|
||
/// 获取农历年份,范围约0-9999年
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static string GetYear(int AYear, int AMonth, int ADay)
|
||
{
|
||
GetLunarFromDay(AYear, AMonth, ADay, out int LunarYear, out int LunarMonth, out int LunarDay, out bool IsLeapMonth);
|
||
string yearTG = "甲乙丙丁戊己庚辛壬癸";
|
||
string yearDZ = "子丑寅卯辰巳午未申酉戌亥";
|
||
string yearSX = "鼠牛虎兔龙蛇马羊猴鸡狗猪";
|
||
int year = LunarYear;
|
||
int yTG = (LunarYear-3)%10;
|
||
if (yTG == 0) { yTG = 10; }
|
||
int yDZ = (AYear - 3) % 12;
|
||
if (yDZ == 0) { yDZ = 12; }
|
||
if (AMonth == 2)
|
||
{
|
||
GetJieQiInAYear(AYear, 2, out int _Month, out int _ADay, out int _, out int _);
|
||
if(ADay< _ADay) { yDZ--; if (yDZ == 0) { yDZ = 12; } }
|
||
}
|
||
else if (AMonth < 2) { yDZ--; if (yDZ == 0) { yDZ = 12; } }
|
||
string str = string.Format("[{0}]{1}{2}年", yearSX[yDZ-1], yearTG[yTG-1], yearDZ[yDZ-1]);
|
||
return str;
|
||
}
|
||
/// <summary>
|
||
/// 获取农历月份,范围约1901-2101年
|
||
/// </summary>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public static string GetMonth(DateTime dt)
|
||
{
|
||
return GetMonth(dt.Year,dt.Month,dt.Day);
|
||
}
|
||
/// <summary>
|
||
/// 获取农历月份,范围约0-9999年
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static string GetMonth(int AYear, int AMonth, int ADay)
|
||
{
|
||
GetLunarMonthDayFromDay(AYear, AMonth, ADay, out int iMonth, out int TempLunarDay, out bool isLeapMonth);
|
||
string strMonth = isLeapMonth ? "闰" : "";
|
||
return strMonth + GetMonth(iMonth);
|
||
}
|
||
/// <summary>
|
||
/// 获取中文表示的农历月份
|
||
/// </summary>
|
||
/// <param name="iMonth"></param>
|
||
/// <returns></returns>
|
||
public static string GetMonth(int iMonth)
|
||
{
|
||
string szText = "正二三四五六七八九十";
|
||
var strMonth = "";
|
||
if (iMonth <= 10)
|
||
{
|
||
strMonth += szText.Substring(iMonth - 1, 1);
|
||
}
|
||
else if (iMonth == 11)
|
||
{
|
||
strMonth += "冬";
|
||
}
|
||
else
|
||
{
|
||
strMonth += "腊";
|
||
}
|
||
return strMonth + "月";
|
||
}
|
||
/// <summary>
|
||
/// 获取农历日,范围约1901-2101年
|
||
/// </summary>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public static string GetDay(DateTime dt)
|
||
{
|
||
return GetDay(dt.Year,dt.Month,dt.Day);
|
||
}
|
||
/// <summary>
|
||
/// 获取农历日,范围约0-9999年
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static string GetDay(int AYear, int AMonth, int ADay)
|
||
{
|
||
GetLunarFromDay(AYear, AMonth, ADay, out int LunarYear, out int LunarMonth, out int LunarDay, out bool IsLeapMont);
|
||
return GetDay(LunarDay);
|
||
}
|
||
/// <summary>
|
||
/// 获取农历日,范围约0-9999年
|
||
/// </summary>
|
||
/// <param name="iDay"></param>
|
||
/// <returns></returns>
|
||
public static string GetDay(int iDay)
|
||
{
|
||
string szText1 = "初十廿三";
|
||
string szText2 = "一二三四五六七八九十";
|
||
string strDay="";
|
||
if (iDay == 20)
|
||
{
|
||
strDay = "二十";
|
||
}
|
||
else if (iDay == 30)
|
||
{
|
||
strDay = "三十";
|
||
}
|
||
else if (iDay>0)
|
||
{
|
||
strDay = szText1.Substring((iDay - 1) / 10, 1);
|
||
strDay = strDay + szText2.Substring((iDay - 1) % 10, 1);
|
||
}
|
||
return strDay;
|
||
}
|
||
/// <summary>
|
||
/// 获取节气,范围约1901-2101年
|
||
/// </summary>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public static string GetSolarTerm(DateTime dt)
|
||
{
|
||
int index = GetJieQiFromDay(dt.Year, dt.Month, dt.Day);
|
||
if (index == -1)
|
||
{ return ""; }
|
||
return JQ[index];
|
||
}
|
||
/// <summary>
|
||
/// 获取节气,范围约0-9999年
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static string GetSolarTerm(int AYear, int AMonth, int ADay)
|
||
{
|
||
int index = GetJieQiFromDay(AYear, AMonth, ADay);
|
||
if (index == -1)
|
||
{ return ""; }
|
||
return JQ[index];
|
||
}
|
||
/// <summary>
|
||
/// 返回y年第n个节气(如小寒为1)的日差天数值(pd取值真假,分别表示平气和定气)
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="N"></param>
|
||
/// <param name="pd">pd取值真假,分别表示平气和定气</param>
|
||
/// <returns></returns>
|
||
public static double GetJieQiDayTimeFromYear(int AYear, int N, bool pd)
|
||
{
|
||
double juD, tht, yrD, shuoD;
|
||
if (AYear <= 0) { AYear++; } // 对没有公元 0 年的调整
|
||
juD = AYear * (365.2423112 - 6.4e-14 * (AYear - 100) * (AYear - 100)
|
||
- 3.047e-8 * (AYear - 100)) + 15.218427 * N + 1721050.71301;
|
||
tht = 3e-4 * AYear - 0.372781384 - 0.2617913325 * N;
|
||
yrD = (1.945 * Math.Sin(tht) - 0.01206 * Math.Sin(2 * tht)) * (1.048994 - 2.583e-5 * AYear);
|
||
shuoD = -18e-4 * Math.Sin(2.313908653 * AYear - 0.439822951 - 3.0443 * N);
|
||
return (pd) ?(juD + yrD + shuoD - GetEquStandardDays(AYear, 1, 0) - 1721425):(juD - GetEquStandardDays(AYear, 1, 0) - 1721425); // 定气
|
||
}
|
||
private static TCalendarType GetCalendarType(int AYear, int AMonth, int ADay)
|
||
{
|
||
if (AYear > 1582)
|
||
return TCalendarType.ctGregorian;
|
||
else if (AYear < 1582)
|
||
return TCalendarType.ctJulian;
|
||
else if (AMonth < 10)
|
||
return TCalendarType.ctJulian;
|
||
else if ((AMonth == 10) && (ADay <= 4))
|
||
return TCalendarType.ctJulian;
|
||
else if ((AMonth == 10) && (ADay >= 5 && ADay <= 14))
|
||
return TCalendarType.ctInvalid;
|
||
else
|
||
return TCalendarType.ctGregorian;
|
||
}
|
||
/// <summary>
|
||
/// 获取等效标准日数
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static int GetEquStandardDays(int AYear, int AMonth, int ADay)
|
||
{
|
||
TCalendarType AType = GetCalendarType(AYear, AMonth, ADay);
|
||
if (AType == TCalendarType.ctGregorian)
|
||
{
|
||
int aa = (AYear - 1) * 365 + ((AYear - 1) / 4) - ((AYear - 1) / 100)
|
||
+ ((AYear - 1) / 400);
|
||
return (AYear - 1) * 365 + ((AYear - 1) / 4) - ((AYear - 1) / 100)
|
||
+ ((AYear - 1) / 400) + GetDayFromYearBegin(AYear, AMonth, ADay);
|
||
}
|
||
else if (AType == TCalendarType.ctJulian)
|
||
{
|
||
return (AYear - 1) * 365 + ((AYear - 1) / 4)
|
||
+ GetDayFromYearBegin(AYear, AMonth, ADay) - 2;
|
||
}
|
||
return 0;
|
||
}
|
||
private static int GetDayFromYearBegin(int AYear, int AMonth, int ADay)
|
||
{
|
||
int[] JQData1 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
|
||
int[] JQData2 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
|
||
bool IsLeapYear = GetIsLeapYear(AYear);
|
||
if (IsLeapYear)
|
||
{
|
||
return JQData2[AMonth - 1] + ADay;
|
||
}
|
||
else
|
||
{
|
||
return JQData1[AMonth - 1] + ADay;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 取本月天数,不考虑 1582 年 10 月的特殊情况
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <returns></returns>
|
||
private static int GetMonthDays(int AYear, int AMonth)
|
||
{
|
||
switch (AMonth)
|
||
{
|
||
case 1:
|
||
case 3:
|
||
case 5:
|
||
case 7:
|
||
case 8:
|
||
case 10:
|
||
case 12:
|
||
return 31;
|
||
case 4:
|
||
case 6:
|
||
case 9:
|
||
case 11:
|
||
return 30;
|
||
case 2:
|
||
if (GetIsLeapYear(AYear))
|
||
{ return 29; }
|
||
else { return 28; }
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 获取节气,范围约1901-2101年
|
||
/// </summary>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public static int GetJieQiFromDay(DateTime dt)
|
||
{
|
||
return GetJieQiFromDay(dt.Year, dt.Month, dt.Day);
|
||
}
|
||
/// <summary>
|
||
/// 获取节气,范围约0-9999年
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static int GetJieQiFromDay(int AYear, int AMonth, int ADay)
|
||
{
|
||
int Idx;
|
||
int result = -1;
|
||
Idx = (AMonth - 1) * 2;
|
||
if (ADay >= 15) { Idx++; }
|
||
if (GetJieQiInAYear(AYear, Idx, out int Month, out int Day, out int DummyHour, out int DummyMinute))
|
||
{
|
||
if ((AMonth == Month) && (ADay == Day))
|
||
{
|
||
// 此时 I 表示 0 是小寒
|
||
result = Idx - 2;
|
||
// 转换成 0 是立春
|
||
if (result < 0)
|
||
result += 24;
|
||
return result;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
/// <summary>
|
||
/// 获取节气
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="N"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <param name="AHour"></param>
|
||
/// <param name="AMinitue"></param>
|
||
/// <returns></returns>
|
||
public static bool GetJieQiInAYear(int AYear, int N, out int AMonth, out int ADay, out int AHour, out int AMinitue)
|
||
{
|
||
double Days;
|
||
int Day;
|
||
bool Result = N >= 0 && N <= 23;
|
||
AMonth = 1;
|
||
if (Result)
|
||
{
|
||
Days = GetJieQiDayTimeFromYear(AYear, N + 1,true);
|
||
for (int i = 1; i <= 12; i++)
|
||
{
|
||
Day = GetMonthDays(AYear, i);
|
||
if (Days > Day)
|
||
{
|
||
Days = Days - Day;
|
||
}
|
||
else
|
||
{
|
||
AMonth = i; break;
|
||
}
|
||
}
|
||
ADay = Convert.ToInt32(Math.Floor(Days));
|
||
Days = Days - ADay;
|
||
AHour = Convert.ToInt32(Math.Floor(Days * 24));
|
||
Days = Days * 24 - AHour;
|
||
AMinitue = Convert.ToInt32(Math.Round(Days * 60));
|
||
// 如果分恰好等于 60,则小时数要加一,如果小时恰好到了 24,则天数要加一
|
||
if (AMinitue >= 60)
|
||
{
|
||
AMinitue -= 60; AHour++;
|
||
if (AHour >= 24) { AHour -= 24; ADay++; }
|
||
// 节气不在月底,因此一般不用考虑天数加一后月份改变的情况
|
||
}
|
||
}
|
||
else
|
||
{
|
||
AMonth = 0;
|
||
ADay = 0;
|
||
AHour = 0;
|
||
AMinitue = 0;
|
||
}
|
||
return Result;
|
||
}
|
||
private static bool GetIsLeapYear(int AYear)
|
||
{
|
||
if (GetCalendarType(AYear, 1, 1) == TCalendarType.ctGregorian)
|
||
{
|
||
return (AYear % 4 == 0) && ((AYear % 100 != 0) || (AYear % 400 == 0));
|
||
}
|
||
else if (AYear >= 0)
|
||
{
|
||
return (AYear % 4 == 0);
|
||
}
|
||
else // 需要独立判断公元前的原因是没有公元 0 年
|
||
{
|
||
return (AYear - 3) % 4 == 0;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 获取公历节日
|
||
/// </summary>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public static string GetHoliday(DateTime dt)
|
||
{
|
||
return GetHoliday(dt.Year, dt.Month,dt.Day);
|
||
}
|
||
/// <summary>
|
||
/// 获取公历节日
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static string GetHoliday(int AYear, int AMonth, int ADay)
|
||
{
|
||
string strReturn = "";
|
||
object g = gHoliday[AMonth.ToString("00") + ADay.ToString("00")];
|
||
if (g != null)
|
||
{
|
||
strReturn = GetHolidayStr(g.ToString(), new DateTime(AYear, AMonth, ADay));
|
||
}
|
||
return strReturn;
|
||
}
|
||
private static string GetHolidayStr(string str,DateTime dt)
|
||
{
|
||
if (str.IndexOf(":") > 0)
|
||
{
|
||
string[] g_split = str.Split(':');
|
||
string[] year_split = g_split[1].Split('-');
|
||
if (year_split.Length == 1)
|
||
{
|
||
if (dt.Year >= year_split[0].ToInt())
|
||
{ return g_split[0]; }
|
||
else { return ""; }
|
||
}
|
||
else if (year_split.Length == 2) { if (dt.Year >= year_split[0].ToInt() && dt.Year <= year_split[1].ToInt()) { return g_split[0]; } else { return ""; } }
|
||
}
|
||
return str;
|
||
}
|
||
/// <summary>
|
||
/// 获取指定月份的第n个星期几的节日
|
||
/// </summary>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public static string GetWeekHoliday(DateTime dt)
|
||
{
|
||
string strReturn = "";
|
||
int week= RyDate.GetWeek_index(dt);
|
||
int week_num = (dt.Day / 7) + 1;
|
||
if(dt.Day % 7 == 0) { week_num--; }
|
||
object g = wHoliday[dt.Month.ToString("00") + week_num.ToString()+ week.ToString()];
|
||
if (g != null)
|
||
{
|
||
strReturn = GetHolidayStr(g.ToString(),dt);
|
||
}
|
||
if(dt.AddDays(7).Month!=dt.Month)
|
||
{
|
||
object g1 = wHoliday[dt.Month.ToString("00") + "0" + week.ToString()];
|
||
if (g1 != null)
|
||
{
|
||
strReturn +=" "+ GetHolidayStr(g1.ToString(), dt);
|
||
}
|
||
}
|
||
return strReturn.Trim();
|
||
}
|
||
/// <summary>
|
||
/// 返回星座,范围约1901-2101年
|
||
/// </summary>
|
||
public static string GetXingzuo(DateTime solarDateTime)
|
||
{
|
||
return GetXingzuo(solarDateTime.Month, solarDateTime.Day);
|
||
}
|
||
/// <summary>
|
||
/// 返回星座,范围约0-9999年
|
||
/// </summary>
|
||
public static string GetXingzuo(int AMonth, int ADay)
|
||
{
|
||
int constellation = -1;
|
||
int Y = AMonth * 100 + ADay;
|
||
if (((Y >= 321) && (Y <= 419))) { constellation = 0; }
|
||
else if ((Y >= 420) && (Y <= 520)) { constellation = 1; }
|
||
else if ((Y >= 521) && (Y <= 620)) { constellation = 2; }
|
||
else if ((Y >= 621) && (Y <= 722)) { constellation = 3; }
|
||
else if ((Y >= 723) && (Y <= 822)) { constellation = 4; }
|
||
else if ((Y >= 823) && (Y <= 922)) { constellation = 5; }
|
||
else if ((Y >= 923) && (Y <= 1022)) { constellation = 6; }
|
||
else if ((Y >= 1023) && (Y <= 1121)) { constellation = 7; }
|
||
else if ((Y >= 1122) && (Y <= 1221)) { constellation = 8; }
|
||
else if ((Y >= 1222) || (Y <= 119)) { constellation = 9; }
|
||
else if ((Y >= 120) && (Y <= 218)) { constellation = 10; }
|
||
else if ((Y >= 219) && (Y <= 320)) { constellation = 11; }
|
||
|
||
string con = "白羊金牛双子巨蟹狮子处女天秤天蝎射手摩羯水瓶双鱼";
|
||
return con.Substring(2 * constellation, 2) + "座";
|
||
}
|
||
/// <summary>
|
||
/// 获取农历节日
|
||
/// </summary>
|
||
/// <param name="AYear"></param>
|
||
/// <param name="AMonth"></param>
|
||
/// <param name="ADay"></param>
|
||
/// <returns></returns>
|
||
public static string GetChinaHoliday(int AYear, int AMonth, int ADay)
|
||
{
|
||
string strReturn = "";
|
||
GetLunarFromDay(AYear, AMonth, ADay, out int LunarYear, out int LunarMonth, out int LunarDay, out bool IsLeapMonth);
|
||
int year = LunarYear;
|
||
int iMonth = LunarMonth;
|
||
int iDay = LunarDay;
|
||
if (iMonth == 12 && GetLunarMonthDays(LunarYear, LunarMonth, IsLeapMonth) == iDay)
|
||
{
|
||
strReturn = "除夕";
|
||
}
|
||
else if (!IsLeapMonth)
|
||
{
|
||
object n = nHoliday[iMonth.ToString("00") + iDay.ToString("00")];
|
||
if (n != null)
|
||
{
|
||
if (strReturn == "")
|
||
{
|
||
strReturn = GetHolidayStr(n.ToString(), new DateTime(AYear, AMonth, ADay));
|
||
}
|
||
else
|
||
{
|
||
strReturn += " " + GetHolidayStr(n.ToString(), new DateTime(AYear, AMonth, ADay));
|
||
}
|
||
}
|
||
}
|
||
|
||
return strReturn;
|
||
}
|
||
/// <summary>
|
||
/// 获取农历节日
|
||
/// </summary>
|
||
/// <param name="dt"></param>
|
||
/// <returns></returns>
|
||
public static string GetChinaHoliday(DateTime dt)
|
||
{
|
||
return GetChinaHoliday(dt.Year,dt.Month,dt.Day);
|
||
}
|
||
/// <summary>
|
||
/// 判断y年m月(1,2,..,12,下同)d日是Gregorian历还是Julian历(opt=1,2,3分别表示标准日历,Gregorge历和Julian历),是则返回1,是Julian历则返回0,若是Gregorge历所删去的那10天则返回-1
|
||
/// </summary>
|
||
private static int IfGregorian(int y, int m, int d, int opt)
|
||
{
|
||
if (opt == 1)
|
||
{
|
||
if (y > 1582 || (y == 1582 && m > 10) || (y == 1582 && m == 10 && d > 14))
|
||
return (1); //Gregorian
|
||
else
|
||
if (y == 1582 && m == 10 && d >= 5 && d <= 14)
|
||
return (-1); //空
|
||
else
|
||
return (0); //Julian
|
||
}
|
||
|
||
if (opt == 2)
|
||
return (1); //Gregorian
|
||
if (opt == 3)
|
||
return (0); //Julian
|
||
return (-1);
|
||
}
|
||
/// <summary>
|
||
/// 返回阳历y年m月d日的日差天数(在y年年内所走过的天数,如2000年3月1日为61)
|
||
/// </summary>
|
||
private static int DayDifference(int y, int m, int d)
|
||
{
|
||
int ifG = IfGregorian(y, m, d, 1);
|
||
int[] monL = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||
if (ifG == 1)
|
||
if ((y % 100 != 0 && y % 4 == 0) || (y % 400 == 0))
|
||
monL[2] += 1;
|
||
else
|
||
if (y % 4 == 0)
|
||
monL[2] += 1;
|
||
int v = 0;
|
||
for (int i = 0; i <= m - 1; i++)
|
||
{
|
||
v += monL[i];
|
||
}
|
||
v += d;
|
||
if (y == 1582)
|
||
{
|
||
if (ifG == 1)
|
||
v -= 10;
|
||
if (ifG == -1)
|
||
v = 0; //infinity
|
||
}
|
||
return v;
|
||
}
|
||
/// <summary>
|
||
/// 返回阳历y年日差天数为x时所对应的月日数(如y=2000,x=274时,返回1001(表示10月1日,即返回100*m+d))
|
||
/// </summary>
|
||
private static double AntiDayDifference(int y, double x)
|
||
{
|
||
int m = 1;
|
||
for (int j = 1; j <= 12; j++)
|
||
{
|
||
int mL = DayDifference(y, j + 1, 1) - DayDifference(y, j, 1);
|
||
if (x <= mL || j == 12)
|
||
{
|
||
m = j;
|
||
break;
|
||
}
|
||
else
|
||
x -= mL;
|
||
}
|
||
return 100 * m + x;
|
||
}
|
||
/// <summary>
|
||
/// 获取指定日期的节气。
|
||
/// </summary>
|
||
/// <param name="year">要获取的年</param>
|
||
/// <param name="month">要获取的月</param>
|
||
/// <returns></returns>
|
||
/// <remarks>
|
||
/// 立春:立是开始的意思,春是蠢动,表示万物开始有生气,这一天春天开始。
|
||
/// 雨水:降雨开始,雨水将多。
|
||
/// 惊蛰:春雷响动,惊动蛰伏地下冬眠的生物,它们将开始出土活动。
|
||
/// 春分:这是春季九十天的中分点,这一天昼夜相等,所以古代曾称春分秋分为昼夜分。
|
||
/// 清明:明洁晴朗,气候温暖,草木开始萌发繁茂。
|
||
/// 谷雨:雨生百谷的意思。雨水增多,适时的降雨对谷物生长很为有利。
|
||
/// 立夏:夏天开始,万物渐将随温暖的气候而生长。
|
||
/// 小满:满指籽粒饱满,麦类等夏热作物这时开始结籽灌浆,即将饱满。
|
||
/// 芒种:有芒作物开始成熟,此时也是秋季作物播种的最繁忙时节。
|
||
/// 夏至:白天最长,黑夜最短,这一天中午太阳位置最高,日影短至终极,古代又称这一天为日北至或长日至。
|
||
/// 小暑:暑是炎热,此时还未到达最热。
|
||
/// 大暑:炎热的程度到达高峰。
|
||
/// 立秋:秋天开始,植物快成熟了。
|
||
/// 处暑:处是住的意思,表示暑气到此为止。
|
||
/// 白露:地面水气凝结为露,色白,是天气开始转凉了。
|
||
/// 秋分:秋季九十天的中间,这一天昼夜相等,同春分一样,太阳从正东升起正西落下。
|
||
/// 寒露:水露先白而后寒,是气候将逐渐转冷的意思。
|
||
/// 霜降:水气开始凝结成霜。
|
||
/// 立冬:冬是终了,作物收割后要收藏起来的意思,这一天起冬天开始。
|
||
/// 小雪:开始降雪,但还不多。
|
||
/// 大雪:雪量由小增大。
|
||
/// 冬至:这一天中午太阳在天空中位置最低,日影最长,白天最短, 黑夜最长,古代又称短日至或日南至。
|
||
/// 小寒:冷气积久而为寒,此时尚未冷到顶点。
|
||
/// 大寒:天候达到最寒冷的程度
|
||
/// </remarks>
|
||
public static SolarTerm[] GetSolarTerm(int year, int month)
|
||
{
|
||
string[] lunarHoliDayName ={
|
||
"小寒", "大寒", "立春", "雨水","惊蛰", "春分", "清明", "谷雨","立夏", "小满", "芒种", "夏至",
|
||
"小暑", "大暑", "立秋", "处暑","白露", "秋分", "寒露", "霜降","立冬", "小雪", "大雪", "冬至"};
|
||
SolarTerm[] solarTerm = new SolarTerm[2];
|
||
|
||
for (int n = month * 2 - 1; n <= month * 2; n++)
|
||
{
|
||
SolarTerm st = new SolarTerm();
|
||
double dd = GetJieQiDayTimeFromYear(year, n, true);
|
||
double sd1 = AntiDayDifference(2005, Math.Floor(dd));
|
||
double sm1 = Math.Floor(sd1 / 100);
|
||
int h = (int)Math.Floor(GetTail(dd) * 24);
|
||
int min = (int)Math.Floor((GetTail(dd) * 24 - h) * 60);
|
||
int mmonth = (int)Math.Ceiling((double)n / 2);
|
||
int day = (int)sd1 % 100;
|
||
st.SolarTermDateTime = new DateTime(year, mmonth, day, h, min, 0);
|
||
st.Name = lunarHoliDayName[n - 1];
|
||
solarTerm[n - month * 2 + 1] = st;
|
||
}
|
||
return solarTerm;
|
||
}
|
||
#region 天干地支
|
||
/// <summary>
|
||
/// 获取年柱。
|
||
/// </summary>
|
||
public static int GetEraYear(DateTime solarDateTime)
|
||
{
|
||
int g = (solarDateTime.Year - 1900 + 36) % 60;
|
||
if ((DayDifference(solarDateTime.Year, solarDateTime.Month, solarDateTime.Day) + solarDateTime.Hour / 24) < GetJieQiDayTimeFromYear(solarDateTime.Year, 3, true) - 1)
|
||
{//判断是否过立春
|
||
g -= 1;
|
||
}
|
||
return g + 1;
|
||
}
|
||
/// <summary>
|
||
/// 获得月柱
|
||
/// </summary>
|
||
/// <param name="solarDateTime"></param>
|
||
/// <returns></returns>
|
||
public static int GetEraMonth(DateTime solarDateTime)
|
||
{
|
||
int v = ((solarDateTime.Year - 1900) * 12 + solarDateTime.Month + 12) % 60;
|
||
if (solarDateTime.Day <= GetSolarTerm(solarDateTime.Year, solarDateTime.Month)[0].SolarTermDateTime.Day)
|
||
v -= 1;
|
||
return v + 1;
|
||
}
|
||
/// <summary>
|
||
/// 获取日柱。
|
||
/// </summary>
|
||
public static int GetEraDay(DateTime solarDateTime)
|
||
{
|
||
double gzD = (solarDateTime.Hour < 23) ? GetEquStandardDays(solarDateTime.Year, solarDateTime.Month, solarDateTime.Day) : GetEquStandardDays(solarDateTime.Year, solarDateTime.Month, solarDateTime.Day) + 1;
|
||
return (int)Math.Round((double)GetRemain((int)gzD + 15, 60));
|
||
}
|
||
/// <summary>
|
||
/// 返回甲子数x对应的天干数(如33为3)
|
||
/// </summary>
|
||
private static int Gan(int x)
|
||
{
|
||
return x % 10;
|
||
}
|
||
/// <summary>
|
||
/// 返回甲子数x对应的地支数(如33为9)
|
||
/// </summary>
|
||
private static int Zhi(int x)
|
||
{
|
||
return x % 12;
|
||
}
|
||
/// <summary>
|
||
/// 获取日的天干地支
|
||
/// </summary>
|
||
/// <param name="solarDateTime"></param>
|
||
/// <returns></returns>
|
||
public static string GetDayTGDZ(DateTime solarDateTime)
|
||
{
|
||
string yearTG = "甲乙丙丁戊己庚辛壬癸";
|
||
string yearDZ = "子丑寅卯辰巳午未申酉戌亥";
|
||
int dG = Gan(GetEraDay(solarDateTime));
|
||
int dZ = Zhi(GetEraDay(solarDateTime));
|
||
if (dG == 0) { dG = 10; }
|
||
if (dZ == 0) { dZ = 12; }
|
||
return yearTG.Substring(dG - 1, 1) + yearDZ.Substring(dZ - 1, 1);
|
||
}
|
||
/// <summary>
|
||
/// 返回甲子数x对应的天干字符串
|
||
/// </summary>
|
||
public static string ToStringWithCelestialStem(int x)
|
||
{
|
||
return "癸甲乙丙丁戊己庚辛壬".Substring(x % 10, 1);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回甲子数x对应的地支字符串
|
||
/// </summary>
|
||
public static string ToStringWithTerrestrialBranch(int x)
|
||
{
|
||
return "亥子丑寅卯辰巳午未申酉戌".Substring(x % 12, 1);
|
||
}
|
||
/// <summary>
|
||
/// 返回甲子数x对应的干支字符串
|
||
/// </summary>
|
||
/// <param name="x"></param>
|
||
/// <returns></returns>
|
||
public static string ToStringWithSexagenary(int x)
|
||
{
|
||
return ToStringWithCelestialStem(x) + ToStringWithTerrestrialBranch(x);
|
||
}
|
||
#endregion
|
||
/// <summary>
|
||
/// 获取三伏开始时间
|
||
/// </summary>
|
||
/// <param name="Year"></param>
|
||
/// <param name="index">0表示1伏,1表示2伏,2表示3伏</param>
|
||
/// <returns></returns>
|
||
public static DateTime Get3Fu(int Year, int index)
|
||
{
|
||
if (index <= 1)
|
||
{
|
||
var day_count = GetJieQiDayTimeFromYear(Year, 12, true);
|
||
var xiazhi_date = new DateTime(Year, 1, 1).AddDays(day_count - 1).Date; //获取夏至 //ToStringWithSexagenary(GetEraDay(xiazhi_date));
|
||
var first_geng_date = xiazhi_date.AddDays(1);//获取夏至后的首个庚日
|
||
for (int i = 0; i < 20; i++)
|
||
{
|
||
if (ToStringWithCelestialStem(GetEraDay(first_geng_date.AddDays(i))) == "庚")
|
||
{
|
||
first_geng_date = first_geng_date.AddDays(i); break;
|
||
}
|
||
}
|
||
if (index == 0) { return first_geng_date.AddDays(20); }
|
||
else if (index == 1) { return first_geng_date.AddDays(30); }
|
||
}
|
||
else if (index == 2)//末伏开始的时间是立秋后的第一个庚日
|
||
{
|
||
var day_count = GetJieQiDayTimeFromYear(Year, 15, true);//立秋
|
||
var liqiu_date = new DateTime(Year, 1, 1).AddDays(day_count - 1).Date; //获取立秋 //ToStringWithSexagenary(GetEraDay(xiazhi_date));
|
||
var first_geng_date = liqiu_date.AddDays(1);//获取立秋后的首个庚日
|
||
for (int i = 0; i < 20; i++)
|
||
{
|
||
if (ToStringWithCelestialStem(GetEraDay(first_geng_date.AddDays(i))) == "庚")
|
||
{
|
||
first_geng_date = first_geng_date.AddDays(i); break;
|
||
}
|
||
}
|
||
return first_geng_date;
|
||
}
|
||
return new DateTime(2000, 1, 1);
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 节气
|
||
/// </summary>
|
||
public class SolarTerm
|
||
{
|
||
private DateTime solarTermDate;
|
||
private string name;
|
||
/// <summary>
|
||
/// 节气的时间。
|
||
/// </summary>
|
||
public DateTime SolarTermDateTime
|
||
{
|
||
get
|
||
{
|
||
return solarTermDate;
|
||
}
|
||
set
|
||
{
|
||
solarTermDate = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 节气名。
|
||
/// </summary>
|
||
public string Name
|
||
{
|
||
get
|
||
{
|
||
return name;
|
||
}
|
||
set
|
||
{
|
||
name = value;
|
||
}
|
||
}
|
||
}
|