using System.Globalization; using System.Collections; using System; using System.Collections.Generic; using ryCommon; /// /// 中国农历类,最大支持公元0-9999年 /// /// 日期:2019-02-09 /// 作者:http://www.cnblogs.com/zjfree/ public static class ChinaDate { /// /// 日历类型 /// public enum TCalendarType { /// /// 无效 /// ctinvalid, /// /// Julian 日历 /// ctJulian, /// /// Gregorian 日历 /// ctGregorian, /// /// 有效 /// ctInvalid } private static ChineseLunisolarCalendar china = new ChineseLunisolarCalendar(); /// /// 公历节日 /// private static readonly Hashtable gHoliday = new Hashtable(); /// /// 农历节日 /// private static readonly Hashtable nHoliday = new Hashtable(); /// /// 某个月第n个星期几 /// 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月的第四个星期四 } /// /// 获取农历 /// /// /// 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; } /// /// 获取农历 /// /// /// /// /// 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]; } } /// /// 获得某农历年的闰月,返回 1~12 对应一月到十二月,返回 0 表示无闰月 /// /// /// public static int GetLunarLeapMonth(int AYear) { int result = GetLeapMonth(AYear); if (result < 0) { result = 0; } return result; } /// /// 农历搜索方向 /// public enum TLunarSearchDirection { /// /// 无效 /// lsdInvalid, /// /// 向上 /// lsdUp, /// /// 向下 /// lsdDown } /// /// {* 日月食类型, 无, 日食, 月全食, 月偏食 } /// public enum TEclipseType { /// /// 无 /// etNone, /// /// 日食 /// etSolar, /// /// 月全食 /// etMoonFull, /// /// 月偏食 /// etMoonHalf } /// /// {* 月相, 无, 朔, 望} /// public enum TMoonPhase { /// /// 无 /// mpNone, /// /// 朔 /// mpShuo, /// /// 望 /// 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; } /// /// 获得某公历年月日的农历日数和该日月相以及日月食类型和时刻 /// /// /// /// /// /// /// /// 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; } /// /// 获得某公历年月日的农历月数 /// /// /// /// /// 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; } /// /// 获取阳历日期对应的农历日期 /// /// /// /// /// /// /// /// /// 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; } /// /// 获得某公历年月日的农历月日和是否闰月的信息 /// /// /// /// /// /// /// /// 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; } /// /// 获得等效标准日数对应的某公历日,倒推而来 /// /// /// /// /// /// 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; } /// /// 比较两个农历日期(包括闰月信息),1 大于2返回1、1等于2返回0、1小于2返回-1 /// /// /// /// /// /// /// /// /// /// 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; } } /// /// 获得某农历年月日(加是否闰月)的公历年月日 /// 该函数采用反向二分法查找 /// /// /// /// /// /// /// /// /// 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; } /// /// 获取农历某一个月的总天数 /// /// /// /// /// 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; } /// /// 获取农历年份,范围约1901-2101年 /// /// /// public static string GetYear(DateTime dt) { return GetYear(dt.Year,dt.Month,dt.Day); } /// /// 获取农历年份,范围约0-9999年 /// /// /// /// /// 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; } /// /// 获取农历月份,范围约1901-2101年 /// /// /// public static string GetMonth(DateTime dt) { return GetMonth(dt.Year,dt.Month,dt.Day); } /// /// 获取农历月份,范围约0-9999年 /// /// /// /// /// 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); } /// /// 获取中文表示的农历月份 /// /// /// 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 + "月"; } /// /// 获取农历日,范围约1901-2101年 /// /// /// public static string GetDay(DateTime dt) { return GetDay(dt.Year,dt.Month,dt.Day); } /// /// 获取农历日,范围约0-9999年 /// /// /// /// /// 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); } /// /// 获取农历日,范围约0-9999年 /// /// /// 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; } /// /// 获取节气,范围约1901-2101年 /// /// /// public static string GetSolarTerm(DateTime dt) { int index = GetJieQiFromDay(dt.Year, dt.Month, dt.Day); if (index == -1) { return ""; } return JQ[index]; } /// /// 获取节气,范围约0-9999年 /// /// /// /// /// public static string GetSolarTerm(int AYear, int AMonth, int ADay) { int index = GetJieQiFromDay(AYear, AMonth, ADay); if (index == -1) { return ""; } return JQ[index]; } /// /// 返回y年第n个节气(如小寒为1)的日差天数值(pd取值真假,分别表示平气和定气) /// /// /// /// pd取值真假,分别表示平气和定气 /// 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; } /// /// 获取等效标准日数 /// /// /// /// /// 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; } } /// /// 取本月天数,不考虑 1582 年 10 月的特殊情况 /// /// /// /// 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; } } /// /// 获取节气,范围约1901-2101年 /// /// /// public static int GetJieQiFromDay(DateTime dt) { return GetJieQiFromDay(dt.Year, dt.Month, dt.Day); } /// /// 获取节气,范围约0-9999年 /// /// /// /// /// 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; } /// /// 获取节气 /// /// /// /// /// /// /// /// 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; } } /// /// 获取公历节日 /// /// /// public static string GetHoliday(DateTime dt) { return GetHoliday(dt.Year, dt.Month,dt.Day); } /// /// 获取公历节日 /// /// /// /// /// 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; } /// /// 获取指定月份的第n个星期几的节日 /// /// /// 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(); } /// /// 返回星座,范围约1901-2101年 /// public static string GetXingzuo(DateTime solarDateTime) { return GetXingzuo(solarDateTime.Month, solarDateTime.Day); } /// /// 返回星座,范围约0-9999年 /// 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) + "座"; } /// /// 获取农历节日 /// /// /// /// /// 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; } /// /// 获取农历节日 /// /// /// public static string GetChinaHoliday(DateTime dt) { return GetChinaHoliday(dt.Year,dt.Month,dt.Day); } /// /// 判断y年m月(1,2,..,12,下同)d日是Gregorian历还是Julian历(opt=1,2,3分别表示标准日历,Gregorge历和Julian历),是则返回1,是Julian历则返回0,若是Gregorge历所删去的那10天则返回-1 /// 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); } /// /// 返回阳历y年m月d日的日差天数(在y年年内所走过的天数,如2000年3月1日为61) /// 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; } /// /// 返回阳历y年日差天数为x时所对应的月日数(如y=2000,x=274时,返回1001(表示10月1日,即返回100*m+d)) /// 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; } /// /// 获取指定日期的节气。 /// /// 要获取的年 /// 要获取的月 /// /// /// 立春:立是开始的意思,春是蠢动,表示万物开始有生气,这一天春天开始。 /// 雨水:降雨开始,雨水将多。 /// 惊蛰:春雷响动,惊动蛰伏地下冬眠的生物,它们将开始出土活动。 /// 春分:这是春季九十天的中分点,这一天昼夜相等,所以古代曾称春分秋分为昼夜分。 /// 清明:明洁晴朗,气候温暖,草木开始萌发繁茂。 /// 谷雨:雨生百谷的意思。雨水增多,适时的降雨对谷物生长很为有利。 /// 立夏:夏天开始,万物渐将随温暖的气候而生长。 /// 小满:满指籽粒饱满,麦类等夏热作物这时开始结籽灌浆,即将饱满。 /// 芒种:有芒作物开始成熟,此时也是秋季作物播种的最繁忙时节。 /// 夏至:白天最长,黑夜最短,这一天中午太阳位置最高,日影短至终极,古代又称这一天为日北至或长日至。 /// 小暑:暑是炎热,此时还未到达最热。 /// 大暑:炎热的程度到达高峰。 /// 立秋:秋天开始,植物快成熟了。 /// 处暑:处是住的意思,表示暑气到此为止。 /// 白露:地面水气凝结为露,色白,是天气开始转凉了。 /// 秋分:秋季九十天的中间,这一天昼夜相等,同春分一样,太阳从正东升起正西落下。 /// 寒露:水露先白而后寒,是气候将逐渐转冷的意思。 /// 霜降:水气开始凝结成霜。 /// 立冬:冬是终了,作物收割后要收藏起来的意思,这一天起冬天开始。 /// 小雪:开始降雪,但还不多。 /// 大雪:雪量由小增大。 /// 冬至:这一天中午太阳在天空中位置最低,日影最长,白天最短, 黑夜最长,古代又称短日至或日南至。 /// 小寒:冷气积久而为寒,此时尚未冷到顶点。 /// 大寒:天候达到最寒冷的程度 /// 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 天干地支 /// /// 获取年柱。 /// 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; } /// /// 获得月柱 /// /// /// 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; } /// /// 获取日柱。 /// 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)); } /// /// 返回甲子数x对应的天干数(如33为3) /// private static int Gan(int x) { return x % 10; } /// /// 返回甲子数x对应的地支数(如33为9) /// private static int Zhi(int x) { return x % 12; } /// /// 获取日的天干地支 /// /// /// 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); } /// /// 返回甲子数x对应的天干字符串 /// public static string ToStringWithCelestialStem(int x) { return "癸甲乙丙丁戊己庚辛壬".Substring(x % 10, 1); } /// /// 返回甲子数x对应的地支字符串 /// public static string ToStringWithTerrestrialBranch(int x) { return "亥子丑寅卯辰巳午未申酉戌".Substring(x % 12, 1); } /// /// 返回甲子数x对应的干支字符串 /// /// /// public static string ToStringWithSexagenary(int x) { return ToStringWithCelestialStem(x) + ToStringWithTerrestrialBranch(x); } #endregion /// /// 获取三伏开始时间 /// /// /// 0表示1伏,1表示2伏,2表示3伏 /// 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); } } /// /// 节气 /// public class SolarTerm { private DateTime solarTermDate; private string name; /// /// 节气的时间。 /// public DateTime SolarTermDateTime { get { return solarTermDate; } set { solarTermDate = value; } } /// /// 节气名。 /// public string Name { get { return name; } set { name = value; } } }