├── .clang-format ├── .gitignore ├── .vscode └── settings.json ├── CMakeLists.txt ├── README.md ├── base ├── CMakeLists.txt ├── base.cxx └── base.h ├── calendar ├── CMakeLists.txt ├── include │ └── calendar.h ├── src │ ├── cal_sx.cxx │ ├── cal_sx.h │ ├── cal_table.cxx │ ├── cal_table.h │ ├── calendar.cxx │ ├── table_data.cxx │ └── table_data.h └── xmake.lua ├── config └── MSystem.cmake ├── images ├── csp_qm_sjzpcjzr.png ├── csp_qm_sjzpcjzr_android.jpg ├── ish.png └── usage.png ├── qimen ├── CMakeLists.txt ├── include │ └── qimen.h └── src │ ├── qimen.cxx │ ├── qm_v1.cxx │ ├── qm_v1.h │ ├── qm_v2.cxx │ ├── qm_v2.h │ ├── qm_v3.cxx │ ├── qm_v3.h │ ├── qm_v4.cxx │ └── qm_v4.h ├── src ├── CLI11.hpp ├── ColorConsole.hpp ├── csp_base.hpp ├── main.cxx ├── print.cxx ├── print.h ├── qmuse.cxx └── qmuse.h ├── sxtwl ├── CMakeLists.txt ├── JD.cpp ├── JD.h ├── SSQ.cpp ├── SSQ.h ├── XL.cpp ├── XL.h ├── const.h ├── day.cpp ├── day.h ├── eph.cpp ├── eph.h ├── sxtwl.cpp ├── sxtwl.h └── xmake.lua └── zhcn ├── CMakeLists.txt ├── xmake.lua ├── zh_lang.cxx └── zh_lang.h /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | IndentWidth: 4 3 | PointerAlignment: Left 4 | AccessModifierOffset: -4 5 | BreakBeforeBraces: Custom 6 | BraceWrapping: 7 | AfterFunction: true 8 | AfterClass: true 9 | Cpp11BracedListStyle: true 10 | ReflowComments: true 11 | SpacesBeforeTrailingComments: 3 12 | TabWidth: 4 13 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 14 | ColumnLimit: 130 15 | AllowShortBlocksOnASingleLine: Never 16 | AllowShortFunctionsOnASingleLine: None 17 | AllowShortEnumsOnASingleLine: false 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .vs 3 | .cache 4 | cmake-* 5 | .xmake -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.autoSave": "onFocusChange", 3 | "editor.fontSize": 14, 4 | "editor.fontFamily": "'Source Code Pro', 'Source Code Pro', monospace", 5 | "terminal.integrated.fontFamily": "Source Code Pro", 6 | "cmake.configureOnOpen": true, 7 | "cmake.debugConfig": { 8 | "console": "integratedTerminal", 9 | "setupCommands": [ 10 | { 11 | "description": "-gdb-set charset utf-8", 12 | "text": "-gdb-set charset UTF-8" 13 | }, 14 | { 15 | "description": "Enable gdb pretty-printing", 16 | "text": "-enable-pretty-printing", 17 | "ignoreFailures": true 18 | } 19 | ], 20 | "args": [ 21 | "-t", "3" 22 | ] 23 | }, 24 | "cmake.configureSettings": { 25 | //"CMAKE_TOOLCHAIN_FILE": "${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" 26 | }, 27 | "cmake.options.statusBarVisibility": "visible", 28 | "cmake.generator": "Ninja", 29 | "C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json", 30 | "C_Cpp.default.cppStandard": "c++17", 31 | "editor.inlayHints.enabled": "off", 32 | "editor.unicodeHighlight.allowedLocales": { 33 | "ja": true, 34 | "zh-hant": true, 35 | "zh-hans": true 36 | }, 37 | "files.associations": { 38 | "xiosbase": "cpp", 39 | "algorithm": "cpp", 40 | "xutility": "cpp", 41 | "vector": "cpp", 42 | "memory": "cpp", 43 | "array": "cpp", 44 | "atomic": "cpp", 45 | "cctype": "cpp", 46 | "clocale": "cpp", 47 | "cmath": "cpp", 48 | "cstddef": "cpp", 49 | "cstdint": "cpp", 50 | "cstdio": "cpp", 51 | "cstdlib": "cpp", 52 | "cstring": "cpp", 53 | "ctime": "cpp", 54 | "cwchar": "cpp", 55 | "exception": "cpp", 56 | "initializer_list": "cpp", 57 | "ios": "cpp", 58 | "iosfwd": "cpp", 59 | "iostream": "cpp", 60 | "istream": "cpp", 61 | "iterator": "cpp", 62 | "limits": "cpp", 63 | "new": "cpp", 64 | "ostream": "cpp", 65 | "stdexcept": "cpp", 66 | "streambuf": "cpp", 67 | "system_error": "cpp", 68 | "tuple": "cpp", 69 | "type_traits": "cpp", 70 | "typeinfo": "cpp", 71 | "utility": "cpp", 72 | "xfacet": "cpp", 73 | "xlocale": "cpp", 74 | "xlocinfo": "cpp", 75 | "xlocnum": "cpp", 76 | "xmemory": "cpp", 77 | "xmemory0": "cpp", 78 | "xstddef": "cpp", 79 | "xstring": "cpp", 80 | "xtr1common": "cpp", 81 | "bit": "cpp", 82 | "compare": "cpp", 83 | "concepts": "cpp", 84 | "*.tcc": "cpp", 85 | "charconv": "cpp", 86 | "cstdarg": "cpp", 87 | "cwctype": "cpp", 88 | "deque": "cpp", 89 | "string": "cpp", 90 | "unordered_map": "cpp", 91 | "functional": "cpp", 92 | "memory_resource": "cpp", 93 | "numeric": "cpp", 94 | "optional": "cpp", 95 | "random": "cpp", 96 | "string_view": "cpp", 97 | "format": "cpp", 98 | "fstream": "cpp", 99 | "numbers": "cpp", 100 | "span": "cpp", 101 | "sstream": "cpp", 102 | "text_encoding": "cpp", 103 | "variant": "cpp", 104 | "map": "cpp", 105 | "bitset": "cpp", 106 | "chrono": "cpp", 107 | "codecvt": "cpp", 108 | "set": "cpp", 109 | "ratio": "cpp", 110 | "regex": "cpp", 111 | "iomanip": "cpp", 112 | "filesystem": "cpp" 113 | }, 114 | "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools" 115 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(csp VERSION 1.4.5 LANGUAGES CXX) 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | 7 | include(config/MSystem.cmake) 8 | if(NOT DEFINED USE_UTF8_ALL) 9 | if (MSVC) 10 | add_compile_options(/source-charset:utf-8) 11 | endif() 12 | set(COMPILER_ID ${CMAKE_CXX_COMPILER_ID}) 13 | if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_SYSTEM_NAME MATCHES "Windows") 14 | MESSAGE(STATUS "ofen Add MinGW Param.") 15 | add_compile_options(-finput-charset=utf-8) 16 | add_compile_options(-fexec-charset=gbk) 17 | set(COMPILER_ID "mingw") 18 | get_filename_component(CXX_COMPILER_PATH ${CMAKE_CXX_COMPILER} DIRECTORY) 19 | set(MINGW32_DLLS 20 | "${CXX_COMPILER_PATH}/libgcc_s_dw2-1.dll" 21 | "${CXX_COMPILER_PATH}/libstdc++-6.dll" 22 | "${CXX_COMPILER_PATH}/libwinpthread-1.dll" 23 | ) 24 | install(FILES ${MINGW32_DLLS} DESTINATION bin) 25 | endif() 26 | else() 27 | add_definitions(-DUSE_UTF8_ALL) 28 | endif() 29 | 30 | set(CMAKE_DEBUG_POSTFIX "d") 31 | message(STATUS "System: ${CMAKE_SYSTEM_NAME}") 32 | message(STATUS "Compiler CXX ID: ${CMAKE_CXX_COMPILER_ID}") 33 | 34 | string(TOLOWER ${COMPILER_ID} COMPILER_ID) 35 | set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}) 36 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}) 37 | 38 | include_directories(src) 39 | add_subdirectory(calendar) 40 | add_subdirectory(qimen) 41 | add_subdirectory(zhcn) 42 | add_subdirectory(sxtwl) 43 | add_subdirectory(base) 44 | add_executable(csp src/main.cxx src/print.cxx src/qmuse.cxx) 45 | target_link_libraries(csp PRIVATE zhcn calendar qm sxtwl) 46 | if(UNAME_OUTPUT MATCHES "alpine" OR UNAME_OUTPUT MATCHES "Alpine") 47 | message(STATUS "csp on musl static link") 48 | target_link_libraries(csp PRIVATE -static;-static-libstdc++) 49 | endif() 50 | 51 | install(TARGETS csp DESTINATION bin) 52 | # ********************************************************** pack infomation 53 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 54 | set(ARCH_BIT "64Bit") 55 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) 56 | set(ARCH_BIT "32Bit") 57 | else() 58 | message(FATAL_ERROR "Unknown target architecture") 59 | endif() 60 | set(CPACK_PACKAGE_NAME "csp") 61 | set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") 62 | set(CPACK_PACKAGE_CONTACT "taynpg ") 63 | set(CPACK_PACKAGE_DESCRIPTION "A Qimen Shipan.") 64 | set(CPACK_PACKAGE_VENDOR "taynpg") 65 | if(WIN32) 66 | set(CPACK_NSIS_MODIFY_PATH ON) 67 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 68 | set(CPACK_GENERATOR "NSIS64;ZIP") 69 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) 70 | set(CPACK_GENERATOR "NSIS;ZIP") 71 | else() 72 | message(FATAL_ERROR "Unknown target architecture") 73 | endif() 74 | set(CPACK_NSIS_INSTALL_ROOT "$PROFILE") 75 | set(CPACK_PACKAGE_INSTALL_DIRECTORY "csp") 76 | elseif(UNIX AND NOT APPLE) 77 | set(CPACK_GENERATOR "DEB;TGZ") 78 | set(CPACK_DEBIAN_PACKAGE_SECTION "utils") 79 | set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") 80 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER "taynpg ") 81 | elseif(APPLE) 82 | set(CPACK_GENERATOR "DragNDrop") 83 | endif() 84 | set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-v${PROJECT_VERSION}-${COMPILER_ID}.${SYSTEM_ARCH}.${ARCH_BIT}") 85 | include(CPack) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 一、csp 简介 2 | 3 | csp-(cpp shi pan,C++式盘),一个cmd命令行起盘工具,计划支持排盘奇门遁甲,大六壬,六爻。 4 | 5 | ## 特点 6 | 7 | - 单机本地、使用过程中无需联网。 8 | - 跨平台(即本项目编译成二进制可执行文件仅需要一个`支持C++11标准`的`编译器`)。 9 | - 支持时间范围广(`一万年跨度`)。 10 | - 支持手机移动端。 11 | 12 | 本项目会长期维护,欢迎您的`PR`。 13 | 14 | **拉取项目请使用:** 15 | 16 | ```shell 17 | git clone https://github.com/taynpg/csp 18 | ``` 19 | 20 | # 二、用法 21 | 22 | 示例图(示例图不一定是最新的,具体看文字功能介绍): 23 | 24 | ![示例图片](https://github.com/taynpg/csp/raw/main/images/usage.png) 25 | 26 | ## 2.2 支持时间范围 27 | 28 | v1.3.1 以前(不含)仅支持: 29 | 30 | 开始日期:1900年01月31日(含)起有效。 31 | 32 | 结束日期:2098年12月31日(含)结束有效。 33 | 34 | v1.3.1 版本及以后已加入寿星万年历,可以支持年跨度`-198~9999`。 35 | 36 | 开始日期:公元前198年01月01日(含)起有效。 37 | 38 | 结束日期:9999年12月31日(含)结束有效。 39 | 40 | 41 | # 三、已实现功能 42 | 43 | - 时家,转盘,超接置润法 44 | - 时家,转盘,阴盘 45 | - 时家,转盘,拆补 46 | - 时家,转盘,茅山 47 | 48 | # 四、构建 49 | 50 | ## 4.1 依赖: 51 | 52 | - 支持C++11语法编译器 53 | 54 | ## 4.2 构建方法: 55 | 56 | 拉取项目请保证网络畅通(可访问`github`)。 57 | 58 | ```shell 59 | $ git clone https://github.com/taynpg/csp 60 | $ cs csp 61 | $ cmake -Bbuild 62 | $ cmake --build build --config Release 63 | ``` 64 | 65 | ## 4.3 手机端构建 66 | 67 | 环境: 68 | 69 | - 安卓端可以使用termux(亲测可用) 70 | 71 | ![termux](https://github.com/taynpg/csp/raw/main/images/csp_qm_sjzpcjzr_android.jpg) 72 | 73 | - iPhone端可以使用iSh(亲测可用) 74 | 75 | ![iSh](https://github.com/taynpg/csp/raw/main/images/ish.png) 76 | 77 | # 五、最后 78 | 79 | 如果您发现了BUG或者有好的建议可以提`issue`或致邮件`taynpg@163.com`(欢迎您的任何想法和咨询)。 80 | -------------------------------------------------------------------------------- /base/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(base LANGUAGES CXX) 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | 7 | if(NOT DEFINED USE_UTF8_ALL) 8 | if (MSVC) 9 | add_compile_options(/source-charset:utf-8) 10 | endif() 11 | if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_SYSTEM_NAME MATCHES "Windows") 12 | MESSAGE(STATUS "base Add MinGW Param.") 13 | add_compile_options(-finput-charset=utf-8) 14 | add_compile_options(-fexec-charset=gbk) 15 | endif() 16 | endif() 17 | 18 | set(SOURCES base.h base.cxx) 19 | 20 | add_library(base STATIC ${SOURCES}) 21 | target_include_directories(base PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -------------------------------------------------------------------------------- /base/base.cxx: -------------------------------------------------------------------------------- 1 | #include "base.h" 2 | 3 | // 0 1 2 3 4 5 6 7 8 9 10 11 4 | // "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" 5 | // 6 | // 甲亥乙午丙戊寅 7 | // 庚巳辛子及壬申 8 | // 丁己在酉癸卯寻 9 | #include 10 | 11 | static std::map sk_{}; 12 | const int g_ZhangSheng[] = {11, 6, 2, 9, 2, 9, 5, 0, 8, 3}; 13 | 14 | namespace csp { 15 | 16 | CBase::CBase() 17 | { 18 | sk_[51] = WUXING_STATE::SHENG; 19 | sk_[52] = WUXING_STATE::KE; 20 | sk_[53] = WUXING_STATE::BEI_KE; 21 | sk_[54] = WUXING_STATE::BEI_SHENG; 22 | sk_[55] = WUXING_STATE::TONG; 23 | 24 | sk_[15] = WUXING_STATE::BEI_SHENG; 25 | sk_[14] = WUXING_STATE::BEI_KE; 26 | sk_[13] = WUXING_STATE::KE; 27 | sk_[12] = WUXING_STATE::SHENG; 28 | sk_[11] = WUXING_STATE::TONG; 29 | 30 | sk_[21] = WUXING_STATE::BEI_SHENG; 31 | sk_[22] = WUXING_STATE::TONG; 32 | sk_[23] = WUXING_STATE::SHENG; 33 | sk_[24] = WUXING_STATE::KE; 34 | sk_[25] = WUXING_STATE::BEI_KE; 35 | 36 | sk_[31] = WUXING_STATE::BEI_KE; 37 | sk_[32] = WUXING_STATE::BEI_SHENG; 38 | sk_[33] = WUXING_STATE::TONG; 39 | sk_[34] = WUXING_STATE::SHENG; 40 | sk_[35] = WUXING_STATE::KE; 41 | 42 | sk_[41] = WUXING_STATE::KE; 43 | sk_[42] = WUXING_STATE::BEI_KE; 44 | sk_[43] = WUXING_STATE::BEI_SHENG; 45 | sk_[44] = WUXING_STATE::TONG; 46 | sk_[45] = WUXING_STATE::SHENG; 47 | } 48 | 49 | CBase::~CBase() = default; 50 | 51 | const int* CBase::zsj() 52 | { 53 | return g_ZhangSheng; 54 | } 55 | 56 | // 金水木火土 数字代表 12345 57 | WUXING_STATE CBase::judge(int me, int other) 58 | { 59 | if (me < 0 || me > 5) { 60 | return WUXING_STATE::NUM_ERROR; 61 | } 62 | if (other < 0 || other > 5) { 63 | return WUXING_STATE::NUM_ERROR; 64 | } 65 | auto ret = sk_[me * 10 + other]; 66 | return ret; 67 | } 68 | 69 | } // namespace csp -------------------------------------------------------------------------------- /base/base.h: -------------------------------------------------------------------------------- 1 | #ifndef BASE_HEADER 2 | #define BASE_HEADER 3 | 4 | namespace csp { 5 | 6 | // 金水木火土 数字代表 12345 7 | enum WUXING_STATE { 8 | KE, // 克别人 9 | BEI_KE, // 被克 10 | SHENG, // 生别人 11 | BEI_SHENG, // 被生 12 | TONG, // 相同 13 | NUM_ERROR // 数字不正确 14 | }; 15 | 16 | class CBase 17 | { 18 | public: 19 | CBase(); 20 | ~CBase(); 21 | 22 | public: 23 | static const int* zsj(); 24 | // 金水木火土 数字代表 12345 25 | WUXING_STATE judge(int me, int other); 26 | }; 27 | } // namespace csp 28 | 29 | #endif -------------------------------------------------------------------------------- /calendar/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(calendar LANGUAGES CXX) 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | 7 | if(NOT DEFINED USE_UTF8_ALL) 8 | if (MSVC) 9 | add_compile_options(/source-charset:utf-8) 10 | endif() 11 | if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_SYSTEM_NAME MATCHES "Windows") 12 | MESSAGE(STATUS "calendar Add MinGW Param.") 13 | add_compile_options(-finput-charset=utf-8) 14 | add_compile_options(-fexec-charset=gbk) 15 | endif() 16 | endif() 17 | 18 | set(CMAKE_DEBUG_POSTFIX "d") 19 | include_directories(include) 20 | include_directories(src) 21 | set(SOURCES 22 | src/calendar.cxx src/cal_table.cxx 23 | src/cal_sx.cxx src/table_data.cxx 24 | ) 25 | add_library(calendar STATIC ${SOURCES}) 26 | target_link_libraries(calendar PRIVATE sxtwl) 27 | target_include_directories(calendar PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) 28 | 29 | if (MSVC) 30 | if(CMAKE_BUILD_TYPE STREQUAL "Release") 31 | string(REPLACE "/O2" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") 32 | target_compile_options(calendar PRIVATE /O1) 33 | endif() 34 | endif() -------------------------------------------------------------------------------- /calendar/include/calendar.h: -------------------------------------------------------------------------------- 1 | #ifndef CALENDAR_H 2 | #define CALENDAR_H 3 | 4 | #include 5 | #include 6 | namespace csp { 7 | 8 | using CSPT = int; 9 | using CSPLT = long long; 10 | enum class CalendarType { 11 | CAL_TYPE_TABLE, // 查表法 12 | CAL_TYPE_SXTWL // 寿星天文历 13 | }; 14 | 15 | struct GanZhi { 16 | CSPT yg{}; // 年干 17 | CSPT yz{}; // 年支 18 | CSPT mg{}; // 月干 19 | CSPT mz{}; // 月支 20 | CSPT dg{}; // 日干 21 | CSPT dz{}; // 日支 22 | CSPT hg{}; // 时干 23 | CSPT hz{}; // 时支 24 | }; 25 | 26 | struct DateTime { 27 | DateTime() = default; 28 | DateTime(CSPT y, CSPT m, CSPT d); 29 | DateTime(CSPT y, CSPT m, CSPT d, CSPT h, CSPT mi, CSPT s); 30 | CSPT year{}; // 年 31 | CSPT mon{}; // 月 32 | CSPT day{}; // 日 33 | CSPT hour{}; // 时 34 | CSPT min{}; // 分 35 | CSPT sec{}; // 秒 36 | CSPT msec{}; // 毫秒 37 | }; 38 | 39 | struct JieQi { 40 | DateTime dt{}; 41 | CSPT index{}; 42 | }; 43 | 44 | class Calendar 45 | { 46 | public: 47 | Calendar(); 48 | virtual ~Calendar() = default; 49 | 50 | public: 51 | /// @brief 获取日历实例 52 | /// @param type 日历类型 53 | /// @return 54 | static std::shared_ptr instance(CalendarType type); 55 | 56 | /// @brief 57 | /// 检查日期合法性,仅检查日期是否格式上合法,不关心实现方是否支持这个范围。 58 | /// @param dt 59 | /// @return 60 | static bool check_format_only(const DateTime& dt); 61 | 62 | /// @brief 判断年份是否时闰年 63 | /// @param year 64 | /// @return 65 | static bool is_leap(CSPT year); 66 | 67 | /// @brief 获取当前时间 68 | /// @return 69 | static DateTime now(); 70 | 71 | /// @brief 对 value 取余数,结果一定大于 0。 72 | /// @param base 73 | /// @param value 74 | /// @return 75 | static CSPT mod(CSPT base, CSPT value); 76 | 77 | /// @brief 判断是否是同一天(不判断时间) 78 | /// @param d 日期一 79 | /// @param p 日期二 80 | /// @return 81 | static bool is_same_day(const DateTime& d, const DateTime& p); 82 | 83 | /// @brief 判断日期和时间是否一致 84 | /// @param d 日期一 85 | /// @param p 日期二 86 | /// @return 87 | static bool is_same_all(const DateTime& d, const DateTime& p); 88 | 89 | /// @brief 判断时间是否一致(不判断日期) 90 | /// @param d 日期一 91 | /// @param p 日期二 92 | /// @return 93 | static bool is_same_time(const DateTime& d, const DateTime& p); 94 | 95 | public: 96 | /// @brief 实现方是否支持此日期 97 | /// @param dt 98 | /// @return 99 | virtual bool is_support(const DateTime& dt) = 0; 100 | 101 | /// @brief 102 | /// 设置某个时间点,并计算相关内容。一般最先调用这个,再使用其他函数。 103 | /// @param dt 104 | /// @return 105 | virtual bool generate(const DateTime& dt) = 0; 106 | 107 | /// @brief 获取公历日期 108 | /// @return 109 | virtual DateTime get_solar() const; 110 | 111 | /// @brief 获取农历日期 112 | /// @return 113 | virtual DateTime get_lunar() const; 114 | 115 | /// @brief 获取前 cnt 天的日期。 116 | /// @param dt 117 | /// @param cnt 118 | virtual void pre_day(DateTime& dt, unsigned int cnt) = 0; 119 | 120 | /// @brief 获取后 cnt 天的日期。 121 | /// @param dt 122 | /// @param cnt 123 | virtual void next_day(DateTime& dt, unsigned int cnt) = 0; 124 | 125 | /// @brief 获取两个时间之间的天数差,计算为 l - r。 126 | /// @param l 127 | /// @param r 128 | /// @return 129 | virtual CSPT days_difference(const DateTime& l, const DateTime& r) = 0; 130 | 131 | /// @brief 根据秒差值计算新日期。 132 | /// @param base 133 | /// @param secs 秒数 134 | /// @return 135 | virtual DateTime cal_new_date(const DateTime& base, CSPLT secs) = 0; 136 | 137 | /// @brief 获取距离 0点的秒数差。 138 | /// @param dt 139 | /// @return 140 | virtual CSPLT cal_zero_secs(const DateTime& dt) = 0; 141 | 142 | /// @brief 获取两个日期时间之间的秒数差(不记入天),计算为 l - r。 143 | /// @param l 144 | /// @param r 145 | /// @return 146 | virtual CSPT calsecs_by_time(const DateTime& l, const DateTime& r) = 0; 147 | 148 | /// @brief 返回两个时间之间的秒数差(记入天),计算为 l - r。 149 | /// @param l 150 | /// @param r 151 | /// @return 152 | virtual CSPLT calsecs_by_all(const DateTime& l, const DateTime& r) = 0; 153 | 154 | /// @brief 获取相邻的6个节气信息 155 | /// @return 156 | std::array get_jq_info() const; 157 | 158 | public: 159 | /// @brief 获取干支信息 160 | /// @return 161 | GanZhi get_ganzhi() const; 162 | 163 | protected: 164 | DateTime solar_{}; // 传入的时间日期 165 | DateTime lunar_{}; // 计算的农历日期 166 | bool leap_{false}; // 当月是否是闰月 167 | bool big_mon_{false}; // 当月是否是大月 168 | GanZhi ganzhi{}; // 此时的干支 169 | 170 | int wuhu_[10]{}; // 五虎遁年起月表 171 | int qishi_[10]{}; // 日上起时表 172 | 173 | std::array jie_{}; 174 | }; 175 | 176 | } // namespace csp 177 | #endif -------------------------------------------------------------------------------- /calendar/src/cal_sx.cxx: -------------------------------------------------------------------------------- 1 | #include "cal_sx.h" 2 | 3 | namespace csp { 4 | CalendarSxwnl::CalendarSxwnl() = default; 5 | 6 | CalendarSxwnl::~CalendarSxwnl() = default; 7 | 8 | bool CalendarSxwnl::generate(const DateTime& dt) 9 | { 10 | if (!is_support(dt)) { 11 | return false; 12 | } 13 | 14 | DateTime h = dt; 15 | if (h.hour == 23) { 16 | next_day(h, 1); 17 | h.hour = 0; 18 | } 19 | solar_ = h; 20 | lunar_ = dt; 21 | day_.reset(sxtwl::fromSolar(solar_.year, solar_.mon, solar_.day)); 22 | 23 | sx2lunar(day_.get(), lunar_); 24 | 25 | ganzhi.yg = day_->getYearGZ().tg; 26 | ganzhi.mg = day_->getMonthGZ().tg; 27 | ganzhi.dg = day_->getDayGZ().tg; 28 | ganzhi.yz = day_->getYearGZ().dz; 29 | ganzhi.mz = day_->getMonthGZ().dz; 30 | ganzhi.dz = day_->getDayGZ().dz; 31 | 32 | auto gz = sxtwl::getShiGz(ganzhi.dg, solar_.hour); 33 | ganzhi.hg = gz.tg; 34 | ganzhi.hz = gz.dz; 35 | 36 | if (dt.hour == 23) { 37 | ganzhi.dg = mod(10, ganzhi.dg + 1); 38 | ganzhi.dz = mod(12, ganzhi.dz + 1); 39 | } 40 | 41 | leap_ = day_->isLunarLeap(); 42 | 43 | std::vector jq_vec{}; 44 | 45 | // 这里之所以这样处理是,接口抛出的结果,从2月开始 46 | if (solar_.mon == 1 || solar_.mon == 2) { 47 | jq_vec = sxtwl::getJieQiByYear(solar_.year - 1); 48 | auto aj = sxtwl::getJieQiByYear(solar_.year); 49 | jq_vec.reserve(jq_vec.size() + aj.size()); 50 | std::copy(aj.begin(), aj.end(), std::back_inserter(jq_vec)); 51 | } else { 52 | jq_vec = sxtwl::getJieQiByYear(solar_.year); 53 | } 54 | 55 | std::vector> cache; 56 | if (solar_.mon == 1) { 57 | cache.emplace_back(std::make_pair(solar_.year - 1, 12)); 58 | cache.emplace_back(std::make_pair(solar_.year, solar_.mon)); 59 | cache.emplace_back(std::make_pair(solar_.year, solar_.mon + 1)); 60 | } else if (solar_.mon == 12) { 61 | cache.emplace_back(std::make_pair(solar_.year, solar_.mon - 1)); 62 | cache.emplace_back(std::make_pair(solar_.year, solar_.mon)); 63 | cache.emplace_back(std::make_pair(solar_.year + 1, 1)); 64 | } else { 65 | cache.emplace_back(std::make_pair(solar_.year, solar_.mon - 1)); 66 | cache.emplace_back(std::make_pair(solar_.year, solar_.mon)); 67 | cache.emplace_back(std::make_pair(solar_.year, solar_.mon + 1)); 68 | } 69 | 70 | std::vector::const_iterator it; 71 | for (it = jq_vec.begin(); it != jq_vec.end(); ++it) { 72 | Time time = sxtwl::JD2DD(it->jd); 73 | // sxtwl 的 jqindex 是从冬至开始的,而 zhcn 是从 74 | // 小寒开始的,所以这里要做一下处理 75 | if (time.getYear() == cache[0].first && time.getMonth() == cache[0].second) { 76 | if (time.getDay() < 15) { 77 | sx2dt(time, jie_[0].dt); 78 | jie_[0].index = mod(24, it->jqIndex - 1); 79 | } else { 80 | sx2dt(time, jie_[1].dt); 81 | jie_[1].index = mod(24, it->jqIndex - 1); 82 | } 83 | continue; 84 | } 85 | if (time.getYear() == cache[1].first && time.getMonth() == cache[1].second) { 86 | if (time.getDay() < 15) { 87 | sx2dt(time, jie_[2].dt); 88 | jie_[2].index = mod(24, it->jqIndex - 1); 89 | } else { 90 | sx2dt(time, jie_[3].dt); 91 | jie_[3].index = mod(24, it->jqIndex - 1); 92 | } 93 | continue; 94 | } 95 | if (time.getYear() == cache[2].first && time.getMonth() == cache[2].second) { 96 | if (time.getDay() < 15) { 97 | sx2dt(time, jie_[4].dt); 98 | jie_[4].index = mod(24, it->jqIndex - 1); 99 | } else { 100 | sx2dt(time, jie_[5].dt); 101 | jie_[5].index = mod(24, it->jqIndex - 1); 102 | } 103 | continue; 104 | } 105 | } 106 | check_mon_gz(); 107 | solar_ = dt; 108 | return true; 109 | } 110 | 111 | bool CalendarSxwnl::is_support(const DateTime& dt) 112 | { 113 | if (dt.year < -198 || dt.year > 9999) { 114 | return false; 115 | } 116 | return true; 117 | } 118 | 119 | void CalendarSxwnl::pre_day(DateTime& dt, unsigned int cnt) 120 | { 121 | std::shared_ptr d(sxtwl::fromSolar(dt.year, dt.mon, dt.day)); 122 | std::shared_ptr pd(d->before(cnt)); 123 | sx2solar(pd.get(), dt); 124 | } 125 | 126 | void CalendarSxwnl::next_day(DateTime& dt, unsigned int cnt) 127 | { 128 | std::shared_ptr d(sxtwl::fromSolar(dt.year, dt.mon, dt.day)); 129 | std::shared_ptr nd(d->after(cnt)); 130 | sx2solar(nd.get(), dt); 131 | } 132 | 133 | CSPT CalendarSxwnl::days_difference(const DateTime& l, const DateTime& r) 134 | { 135 | Time a(l.year, l.mon, l.day, 0, 0, 0); 136 | Time b(r.year, r.mon, r.day, 0, 0, 0); 137 | 138 | double df = sxtwl::toJD(a) - sxtwl::toJD(b); 139 | return static_cast(df); 140 | } 141 | 142 | DateTime CalendarSxwnl::cal_new_date(const DateTime& base, CSPLT secs) 143 | { 144 | Time a(base.year, base.mon, base.day, base.hour, base.min, base.sec); 145 | double da = sxtwl::toJD(a); 146 | double db = da + static_cast(secs / 86400.0); 147 | Time b = sxtwl::JD2DD(db); 148 | DateTime r{}; 149 | sx2dt(b, r); 150 | return r; 151 | } 152 | 153 | CSPLT CalendarSxwnl::cal_zero_secs(const DateTime& dt) 154 | { 155 | return dt.hour * 3600 + dt.min * 60 + dt.sec; 156 | } 157 | 158 | CSPT CalendarSxwnl::calsecs_by_time(const DateTime& l, const DateTime& r) 159 | { 160 | CSPT a = cal_zero_secs(l); 161 | CSPT b = cal_zero_secs(r); 162 | return a - b; 163 | } 164 | 165 | CSPLT CalendarSxwnl::calsecs_by_all(const DateTime& l, const DateTime& r) 166 | { 167 | Time a(l.year, l.mon, l.day, l.hour, l.min, l.sec); 168 | Time b(r.year, r.mon, r.day, r.hour, r.min, r.sec); 169 | 170 | double da = sxtwl::toJD(a); 171 | double db = sxtwl::toJD(b); 172 | double dr = da - db; 173 | return static_cast(dr * 86400); 174 | } 175 | 176 | void CalendarSxwnl::sx2dt(const Time& t, DateTime& dt) 177 | { 178 | auto ct(t); 179 | dt.year = ct.getYear(); 180 | dt.mon = ct.getMonth(); 181 | dt.day = ct.getDay(); 182 | dt.hour = static_cast(ct.getHour()); 183 | dt.min = static_cast(ct.getMin()); 184 | dt.sec = rd(ct.getSec()); 185 | } 186 | 187 | void CalendarSxwnl::sx2lunar(Day* day, DateTime& date) 188 | { 189 | date.year = day->getLunarYear(); 190 | date.mon = static_cast(day->getLunarMonth()); 191 | date.day = day->getLunarDay(); 192 | } 193 | 194 | void CalendarSxwnl::sx2solar(Day* day, DateTime& date) 195 | { 196 | date.year = day->getSolarYear(); 197 | date.mon = static_cast(day->getSolarMonth()); 198 | date.day = day->getSolarDay(); 199 | } 200 | 201 | int CalendarSxwnl::rd(double number) 202 | { 203 | double ret = (number > 0.0) ? (number + 0.5) : (number - 0.5); 204 | return static_cast(ret); 205 | } 206 | 207 | void CalendarSxwnl::check_mon_gz() 208 | { 209 | auto check = [this](const DateTime& dt) { 210 | auto dif = calsecs_by_time(solar_, dt); 211 | if (dif < 0) { 212 | ganzhi.mg = mod(10, ganzhi.mg - 1); 213 | ganzhi.mz = mod(12, ganzhi.mz - 1); 214 | } 215 | }; 216 | check(jie_[2].dt); 217 | } 218 | 219 | } // namespace csp -------------------------------------------------------------------------------- /calendar/src/cal_sx.h: -------------------------------------------------------------------------------- 1 | #ifndef CAL_SXWNL 2 | #define CAL_SXWNL 3 | 4 | #include "calendar.h" 5 | #include 6 | #include 7 | 8 | namespace csp { 9 | class CalendarSxwnl : public Calendar 10 | { 11 | public: 12 | CalendarSxwnl(); 13 | ~CalendarSxwnl() override; 14 | 15 | public: 16 | // 设置某个时间点,并计算相关内容。一般最先调用这个,再使用其他函数。 17 | bool generate(const DateTime& dt) override; 18 | 19 | // 是否支持此日期 20 | bool is_support(const DateTime& dt) override; 21 | 22 | // 获取前 cnt 天的日期。 23 | void pre_day(DateTime& dt, unsigned int cnt) override; 24 | 25 | // 获取后 cnt 天的日期。 26 | void next_day(DateTime& dt, unsigned int cnt) override; 27 | 28 | // 获取两个时间之间的天数差,计算为 l - r。 29 | CSPT days_difference(const DateTime& l, const DateTime& r) override; 30 | 31 | // 根据秒差值计算新日期。 32 | DateTime cal_new_date(const DateTime& base, CSPLT secs) override; 33 | 34 | // 获取距离 0点的秒数差。 35 | CSPLT cal_zero_secs(const DateTime& dt) override; 36 | 37 | // 获取两个日期时间之间的秒数差(不记入天),计算为 l - r。 38 | CSPT calsecs_by_time(const DateTime& l, const DateTime& r) override; 39 | 40 | // 返回两个时间之间的秒数差(记入天),计算为 l - r。 41 | CSPLT calsecs_by_all(const DateTime& l, const DateTime& r) override; 42 | 43 | private: 44 | void sx2dt(const Time& t, DateTime& dt); 45 | void sx2lunar(Day* day, DateTime& date); 46 | void sx2solar(Day* day, DateTime& date); 47 | int rd(double number); 48 | // 根据节气时间修正月干支 49 | void check_mon_gz(); 50 | 51 | private: 52 | std::shared_ptr day_{}; 53 | }; 54 | } // namespace csp 55 | 56 | #endif -------------------------------------------------------------------------------- /calendar/src/cal_table.cxx: -------------------------------------------------------------------------------- 1 | #include "cal_table.h" 2 | #include "table_data.h" 3 | 4 | namespace csp { 5 | 6 | CalendarTable::CalendarTable() 7 | { 8 | init_data(); 9 | } 10 | 11 | CalendarTable::~CalendarTable() 12 | { 13 | } 14 | 15 | bool CalendarTable::generate(const DateTime& dt) 16 | { 17 | if (!is_support(dt)) { 18 | return false; 19 | } 20 | // 这里要特殊处理一下,当23点后,农历要计为次日 21 | DateTime handled = dt; 22 | if (dt.hour == 23) { 23 | next_day(handled, 1); 24 | handled.hour = 0; 25 | } 26 | solar_ = dt; 27 | 28 | DateTime dtt{}; 29 | dtt.year = 1900; 30 | dtt.mon = 1; 31 | dtt.day = 31; 32 | 33 | int offset = days_difference(solar_, dtt); 34 | int i = 0, leap_num = 0, c = 0; 35 | for (i = 1900; i < 2100 && offset > 0; ++i) { 36 | c = get_lunar_days(i); 37 | offset -= c; 38 | } 39 | if (offset < 0) { 40 | offset += c; 41 | --i; 42 | } 43 | 44 | lunar_.year = i; 45 | leap_num = get_leap_mon(i); 46 | leap_ = false; 47 | 48 | for (i = 1; i < 13 && offset > 0; ++i) { 49 | // 闰月 50 | if (leap_num > 0 && i == (leap_num + 1) && (!leap_)) { 51 | --i; 52 | leap_ = true; 53 | c = get_leap_days(lunar_.year); 54 | } else { 55 | c = get_lunar_day(lunar_.year, i); 56 | } 57 | // 解除闰月 58 | if (leap_ && i == (leap_num + 1)) { 59 | leap_ = false; 60 | } 61 | offset -= c; 62 | } 63 | 64 | if (offset == 0 && leap_num > 0 && i == leap_num + 1) { 65 | if (leap_) { 66 | leap_ = false; 67 | } else { 68 | leap_ = true; 69 | --i; 70 | } 71 | } 72 | 73 | if (offset < 0) { 74 | offset += c; 75 | --i; 76 | } 77 | 78 | lunar_.mon = i; 79 | lunar_.day = offset + 1; 80 | big_mon_ = leap_ ? get_leap_days(lunar_.year) != 0 : get_lunar_day(lunar_.year, lunar_.mon) > 29; 81 | 82 | CSPT tyear = solar_.year; 83 | CSPT tmon = solar_.mon; 84 | 85 | if (tmon == 1) { 86 | tyear -= 1; 87 | tmon = 12; 88 | } 89 | 90 | auto jq_gen = [&](CSPT year, CSPT mon, DateTime& dt, JieQi& q, bool f) { 91 | if (f) { 92 | get_lunar_sterm(year, (mon - 1) * 2, dt); 93 | q.index = (dt.mon - 1) * 2; 94 | } else { 95 | get_lunar_sterm(year, (mon - 1) * 2 + 1, dt); 96 | q.index = (dt.mon - 1) * 2 + 1; 97 | } 98 | }; 99 | 100 | jq_gen(tyear, tmon, jie_[0].dt, jie_[0], true); 101 | jq_gen(tyear, tmon, jie_[1].dt, jie_[1], false); 102 | 103 | tyear = solar_.year; 104 | tmon = solar_.mon; 105 | 106 | jq_gen(tyear, tmon, jie_[2].dt, jie_[2], true); 107 | jq_gen(tyear, tmon, jie_[3].dt, jie_[3], false); 108 | 109 | if (tmon == 12) { 110 | tyear += 1; 111 | tmon = 1; 112 | } 113 | 114 | jq_gen(tyear, tmon, jie_[4].dt, jie_[4], true); 115 | jq_gen(tyear, tmon, jie_[5].dt, jie_[5], false); 116 | 117 | // 计算日柱 118 | int day_cnt = get_days_from_base(solar_); 119 | if (solar_.hour == 23) { 120 | ++day_cnt; 121 | } 122 | ganzhi.dg = day_cnt % 10; 123 | ganzhi.dz = (day_cnt + 10) % 12; 124 | 125 | cal_ym_ganzhi(); 126 | cal_hour_ganzhi(); 127 | 128 | return true; 129 | } 130 | 131 | bool CalendarTable::is_support(const DateTime& dt) 132 | { 133 | if (!Calendar::check_format_only(dt)) { 134 | return false; 135 | } 136 | if (dt.year < 1901 || dt.year > 2099) { 137 | return false; 138 | } 139 | return true; 140 | } 141 | 142 | void CalendarTable::pre_day(DateTime& dt, unsigned int cnt) 143 | { 144 | auto pre = [this, &dt]() { 145 | int y = dt.year; 146 | int m = dt.mon; 147 | int d = dt.day; 148 | 149 | if (d > 1) { 150 | --dt.day; 151 | return; 152 | } 153 | if (m > 1) { 154 | if ((m - 1) == 2) { 155 | dt.mon = 2; 156 | if (Calendar::is_leap(y)) { 157 | dt.day = 29; 158 | } else { 159 | dt.day = 28; 160 | } 161 | return; 162 | } 163 | dt.mon = m - 1; 164 | switch (dt.mon) { 165 | case 3: 166 | case 5: 167 | case 7: 168 | case 8: 169 | case 10: { 170 | dt.day = 31; 171 | break; 172 | } 173 | default: { 174 | dt.day = 30; 175 | break; 176 | } 177 | } 178 | return; 179 | } 180 | dt.year = y - 1; 181 | dt.mon = 12; 182 | dt.day = 31; 183 | }; 184 | for (unsigned int i = 0; i < cnt; ++i) { 185 | pre(); 186 | } 187 | } 188 | 189 | void CalendarTable::next_day(DateTime& dt, unsigned int cnt) 190 | { 191 | auto next = [this, &dt]() { 192 | int y = dt.year; 193 | int m = dt.mon; 194 | int d = dt.day; 195 | 196 | int day = 0; 197 | switch (m) { 198 | case 1: 199 | case 3: 200 | case 5: 201 | case 7: 202 | case 8: 203 | case 10: 204 | case 12: { 205 | day = 31; 206 | break; 207 | } 208 | case 2: { 209 | if (Calendar::is_leap(y)) { 210 | day = 29; 211 | } else { 212 | day = 28; 213 | } 214 | break; 215 | } 216 | default: { 217 | day = 30; 218 | break; 219 | } 220 | } 221 | 222 | if (m <= 11) { 223 | if (day == d) { 224 | dt.mon = m + 1; 225 | dt.day = 1; 226 | } else { 227 | dt.mon = m; 228 | dt.day = d + 1; 229 | } 230 | } else if (m == 12) { 231 | if (d == day) { 232 | dt.year = y + 1; 233 | dt.mon = 1; 234 | dt.day = 1; 235 | } else { 236 | dt.mon = 12; 237 | dt.day = d + 1; 238 | } 239 | } 240 | }; 241 | for (unsigned int i = 0; i < cnt; ++i) { 242 | next(); 243 | } 244 | } 245 | 246 | CSPT CalendarTable::days_difference(const DateTime& l, const DateTime& r) 247 | { 248 | return CSPT(); 249 | } 250 | 251 | DateTime CalendarTable::cal_new_date(const DateTime& base, CSPLT secs) 252 | { 253 | auto result = base; 254 | constexpr auto one_day_secs = 24 * 3600; 255 | 256 | int year = base.year; 257 | int mon = base.mon; 258 | int day = base.day; 259 | int hour = base.hour; 260 | int min = base.min; 261 | int sec = base.sec; 262 | 263 | char c{}; 264 | CSPLT n = 0; 265 | CSPLT num = secs / (24 * 3600); 266 | int nr = static_cast(secs % (24 * 3600)); 267 | 268 | // 这里当时我为啥要取反来着? 269 | // if (nr < 0) { 270 | // nr = -nr; 271 | // } 272 | 273 | int bsec = hour * 3600 + min * 60 + sec; 274 | if (num < 0) { 275 | c = '-'; 276 | n = -num; 277 | } else { 278 | c = '+'; 279 | n = num; 280 | } 281 | for (int i = 0; i < n; ++i) { 282 | if (c == '-') { 283 | --day; 284 | if (day == 0) { 285 | --mon; 286 | if (mon == 0) { 287 | mon = 12; 288 | --year; 289 | } 290 | switch (mon) { 291 | case 4: 292 | case 6: 293 | case 9: 294 | case 11: { 295 | day = 30; 296 | break; 297 | } 298 | case 2: { 299 | if (Calendar::is_leap(year)) { 300 | day = 29; 301 | } else { 302 | day = 28; 303 | } 304 | break; 305 | } 306 | default: { 307 | day = 31; 308 | break; 309 | } 310 | } 311 | } 312 | } else { 313 | ++day; 314 | switch (mon) { 315 | case 4: 316 | case 6: 317 | case 9: 318 | case 11: { 319 | if (day == 31) { 320 | day = 1; 321 | ++mon; 322 | } 323 | break; 324 | } 325 | case 2: { 326 | if (Calendar::is_leap(year)) { 327 | if (day == 30) { 328 | day = 1; 329 | ++mon; 330 | } 331 | } else { 332 | if (day == 29) { 333 | day = 1; 334 | ++mon; 335 | } 336 | } 337 | break; 338 | } 339 | default: { 340 | if (day == 32) { 341 | day = 1; 342 | ++mon; 343 | } 344 | break; 345 | } 346 | } 347 | if (mon == 13) { 348 | mon = 1; 349 | ++year; 350 | } 351 | } 352 | } 353 | if (c == '-') { 354 | int nd = bsec - nr; 355 | if (nd >= 0) { 356 | result.hour = nd / 3600; 357 | result.min = (nd % 3600) / 60; 358 | result.sec = nd % 60; 359 | } else { 360 | pre_day(result, 1); 361 | int nt = one_day_secs + nd; 362 | result.hour = nt / 3600; 363 | result.min = (nt % 3600) / 60; 364 | result.sec = nt % 60; 365 | return result; 366 | } 367 | } else { 368 | int nd = bsec + nr; 369 | if (nd > one_day_secs) { 370 | result.year = year; 371 | result.mon = mon; 372 | result.day = day; 373 | result.hour = 12; 374 | result.min = 0; 375 | result.sec = 0; 376 | next_day(result, 1); 377 | nd -= one_day_secs; 378 | result.hour = nd / 3600; 379 | result.min = (nd % 3600) / 60; 380 | result.sec = nd % 60; 381 | return result; 382 | } 383 | result.hour = nd / 3600; 384 | result.min = (nd % 3600) / 60; 385 | result.sec = nd % 60; 386 | } 387 | result.year = year; 388 | result.mon = mon; 389 | result.day = day; 390 | return result; 391 | } 392 | 393 | CSPLT CalendarTable::cal_zero_secs(const DateTime& dt) 394 | { 395 | return dt.hour * 3600 + dt.min * 60 + dt.sec; 396 | } 397 | 398 | CSPT CalendarTable::calsecs_by_time(const DateTime& l, const DateTime& r) 399 | { 400 | int a = cal_zero_secs(l); 401 | int b = cal_zero_secs(r); 402 | return a - b; 403 | } 404 | 405 | CSPLT CalendarTable::calsecs_by_all(const DateTime& l, const DateTime& r) 406 | { 407 | CSPLT a = calsecs_by_time(l, r); 408 | CSPLT b = days_difference(l, r); 409 | return (a + b * 86400); 410 | } 411 | 412 | void CalendarTable::init_data() 413 | { 414 | jq_data_init(difference_jq_); 415 | lunar_data_init(lunar_table_); 416 | } 417 | 418 | CSPT CalendarTable::get_leap_mon(CSPT year) 419 | { 420 | int r = lunar_table_[year - 1900] & 0xf; 421 | if (r == 0xf) { 422 | return 0; 423 | } 424 | return r; 425 | } 426 | 427 | CSPT CalendarTable::get_leap_days(CSPT year) 428 | { 429 | if (get_leap_mon(year)) { 430 | int r = lunar_table_[year - 1899] & 0xf; 431 | if (r == 0xf) { 432 | return 30; 433 | } 434 | return 29; 435 | } 436 | return 0; 437 | } 438 | 439 | CSPT CalendarTable::get_lunar_days(CSPT year) 440 | { 441 | int i = 0, s = 348, n = 0; 442 | for (i = 0x8000; i > 0x8; i >>= 1) { 443 | n = lunar_table_[year - 1900]; 444 | s += (n & i) ? 1 : 0; 445 | } 446 | return s + get_leap_days(year); 447 | } 448 | 449 | CSPT CalendarTable::get_lunar_day(CSPT year, CSPT mon) 450 | { 451 | int r = lunar_table_[year - 1900] & (0x10000 >> mon); 452 | if (r) { 453 | return 30; 454 | } 455 | return 29; 456 | } 457 | 458 | CSPT CalendarTable::get_lunar_sterm(CSPT year, CSPT cnt, DateTime& datetime) 459 | { 460 | CSPT up = (year - 1900) * 24 + cnt; 461 | 462 | CSPLT n = 0; 463 | for (int i = 0; i < up; ++i) { 464 | n = n + difference_jq_[i]; 465 | } 466 | 467 | DateTime d; 468 | d.year = 1900; 469 | d.mon = 1; 470 | d.day = 6; 471 | d.hour = 2; 472 | d.min = 3; 473 | d.sec = 57; 474 | 475 | datetime = cal_new_date(d, n); 476 | return datetime.day; 477 | } 478 | 479 | void CalendarTable::cal_ym_ganzhi() 480 | { 481 | /* 482 | 以公历 1900 年 01 月 6 日时为起始日期(小寒)对应农历日期为 1900 年 己亥年,丁丑月 (以立春为新年) 483 | */ 484 | 485 | int year_gz = 35; // 己亥 的索引 486 | int mon_gz = 13; // 丁丑 的索引  487 | int sjq = 0; // 小寒 的索引 488 | int sy = 1900; 489 | int sm = 1; 490 | 491 | const auto& first_jq = jie_[2]; 492 | int cnt = (solar_.year - 1900) * 24 + first_jq.index; 493 | for (int i = 0; i < cnt; ++i) { 494 | next_mon_info(sy, sm, sjq, mon_gz, year_gz); 495 | } 496 | auto nChange = days_difference(first_jq.dt, solar_); 497 | int mg = 0, mk = 0; 498 | if (nChange < 0) { 499 | mg = year_gz; 500 | mk = mon_gz; 501 | } else { 502 | if (first_jq.index == 2) { 503 | pre_mon_info(year_gz, mon_gz, mg, mk, true); 504 | } else { 505 | pre_mon_info(year_gz, mon_gz, mg, mk, false); 506 | } 507 | } 508 | ganzhi.yg = mg % 10; 509 | ganzhi.yz = mg % 12; 510 | ganzhi.mg = mk % 10; 511 | ganzhi.mz = mk % 12; 512 | } 513 | 514 | void CalendarTable::cal_hour_ganzhi() 515 | { 516 | int ns = qishi_[ganzhi.dg]; 517 | int ng = Calendar::mod(10, ns) * 6; 518 | int jh = solar_.hour + 1; 519 | if (jh == 24) { 520 | jh = 0; 521 | } 522 | ganzhi.hg = Calendar::mod(10, ng + jh / 2); 523 | ganzhi.hz = jh / 2; 524 | } 525 | 526 | CSPT CalendarTable::get_days_from_base(const DateTime& dt) 527 | { 528 | int y = dt.year; 529 | int m = dt.mon; 530 | int d = dt.day; 531 | 532 | int ny = 0, nm = 0, nd = 0, nsum = 0; 533 | 534 | if (y >= 1900) { 535 | for (int i = 1900; i < y; ++i) { 536 | if (Calendar::is_leap(i)) { 537 | ny += 366; 538 | } else { 539 | ny += 365; 540 | } 541 | } 542 | for (int i = 1; i < m; ++i) { 543 | switch (i) { 544 | case 1: 545 | case 3: 546 | case 5: 547 | case 7: 548 | case 8: 549 | case 10: 550 | case 12: 551 | nm += 31; 552 | break; 553 | case 4: 554 | case 6: 555 | case 9: 556 | case 11: 557 | nm += 30; 558 | break; 559 | case 2: { 560 | if (Calendar::is_leap(y)) { 561 | nm += 29; 562 | } else { 563 | nm += 28; 564 | } 565 | break; 566 | } 567 | default: { 568 | break; 569 | } 570 | } 571 | } 572 | nd = d - 1; 573 | nsum = ny + nm + nd; 574 | } else { 575 | for (int i = y; i < 1900; ++i) { 576 | if (Calendar::is_leap(i)) { 577 | ny += 366; 578 | } else { 579 | ny += 365; 580 | } 581 | } 582 | for (int i = 1; i < m; ++i) { 583 | switch (i) { 584 | case 1: 585 | case 3: 586 | case 5: 587 | case 7: 588 | case 8: 589 | case 10: 590 | case 12: 591 | nm += 31; 592 | break; 593 | case 4: 594 | case 6: 595 | case 9: 596 | case 11: 597 | nm += 30; 598 | break; 599 | case 2: { 600 | if (Calendar::is_leap(y)) { 601 | nm += 29; 602 | } else { 603 | nm += 28; 604 | } 605 | break; 606 | } 607 | default: { 608 | break; 609 | } 610 | } 611 | } 612 | nd = d - 1; 613 | nsum = ny - nm - nd; 614 | nsum = -nsum; 615 | } 616 | return nsum; 617 | } 618 | 619 | void CalendarTable::next_mon_info(CSPT& year, CSPT& mon, CSPT& jie, CSPT& jz_mon, CSPT& jz_year) 620 | { 621 | CSPT ns = jie; 622 | if ((ns % 2) == 0) { 623 | jie = Calendar::mod(24, ++ns); 624 | } else { 625 | if ((mon + 1) > 12) { 626 | ++year; 627 | mon = 1; 628 | } else { 629 | ++mon; 630 | } 631 | jie = Calendar::mod(24, ++ns); 632 | if (jie == 2) { // 立春 633 | CSPT n = 0; 634 | next_year_info(jz_year, n, jz_mon); 635 | jz_year = n; 636 | } else { 637 | jz_mon = Calendar::mod(60, jz_mon + 1); 638 | } 639 | } 640 | } 641 | 642 | void CalendarTable::pre_mon_info(CSPT jz_year, CSPT jz_mon, CSPT& jz_year_out, CSPT& jz_mon_out, bool lichun) 643 | { 644 | if (lichun) { 645 | jz_year_out = Calendar::mod(60, jz_year - 1); 646 | int tian = jz_year_out % 10; 647 | int ms = wuhu_[tian]; 648 | jz_mon_out = Calendar::mod(10, (ms - 2)) * 6 + 2; 649 | } else { 650 | jz_year_out = jz_year; 651 | jz_mon_out = Calendar::mod(60, jz_mon - 1); 652 | } 653 | } 654 | 655 | void CalendarTable::next_year_info(CSPT jz_year, CSPT& jz_year_out, CSPT& jz_mon_out) 656 | { 657 | jz_year_out = Calendar::mod(60, jz_year + 1); 658 | int tian = jz_year_out % 10; 659 | int ms = wuhu_[tian]; 660 | jz_mon_out = Calendar::mod(10, (ms - 2)) * 6 + 2; 661 | } 662 | 663 | } // namespace csp -------------------------------------------------------------------------------- /calendar/src/cal_table.h: -------------------------------------------------------------------------------- 1 | #ifndef CAL_TABLE_H 2 | #define CAL_TABLE_H 3 | 4 | #include "calendar.h" 5 | #include 6 | 7 | namespace csp { 8 | constexpr int cnum = 10; 9 | class CalendarTable : public Calendar 10 | { 11 | public: 12 | CalendarTable(); 13 | ~CalendarTable() override; 14 | 15 | public: 16 | // 设置某个时间点,并计算相关内容。一般最先调用这个,再使用其他函数。 17 | bool generate(const DateTime& dt) override; 18 | 19 | // 是否支持此日期 20 | bool is_support(const DateTime& dt) override; 21 | 22 | // 获取前 cnt 天的日期。 23 | void pre_day(DateTime& dt, unsigned int cnt) override; 24 | 25 | // 获取后 cnt 天的日期。 26 | void next_day(DateTime& dt, unsigned int cnt) override; 27 | 28 | // 获取两个时间之间的天数差,计算为 l - r。 29 | CSPT days_difference(const DateTime& l, const DateTime& r) override; 30 | 31 | // 根据秒差值计算新日期。 32 | DateTime cal_new_date(const DateTime& base, CSPLT secs) override; 33 | 34 | // 获取距离 0点的秒数差。 35 | CSPLT cal_zero_secs(const DateTime& dt) override; 36 | 37 | // 获取两个日期时间之间的秒数差(不记入天),计算为 l - r。 38 | CSPT calsecs_by_time(const DateTime& l, const DateTime& r) override; 39 | 40 | // 返回两个时间之间的秒数差(记入天),计算为 l - r。 41 | CSPLT calsecs_by_all(const DateTime& l, const DateTime& r) override; 42 | 43 | private: 44 | void init_data(); 45 | 46 | private: 47 | // 农历指定年所闰的月数,没有返回0 48 | CSPT get_leap_mon(CSPT year); 49 | 50 | // 返回农历 xx 年闰月的天数 51 | CSPT get_leap_days(CSPT year); 52 | 53 | // 返回农历 xx 年的总的天数 54 | CSPT get_lunar_days(CSPT year); 55 | 56 | // 返回农历 xx 年 xx 月的天数 57 | CSPT get_lunar_day(CSPT year, CSPT mon); 58 | 59 | private: 60 | // 获取某年第 x 个节气为几号(从 0 小寒算起) 61 | CSPT get_lunar_sterm(CSPT year, CSPT cnt, DateTime& datetime); 62 | 63 | // 计算农历的年干支,月干支 (立春为新年) 64 | void cal_ym_ganzhi(); 65 | 66 | // 计算时辰的干支(在计算完年月干支后进行) 67 | void cal_hour_ganzhi(); 68 | 69 | private: 70 | // 返回距离 1900.1.1 的天数 71 | static CSPT get_days_from_base(const DateTime& dt); 72 | 73 | // 返回下一个月的年干支月干支信息 74 | void next_mon_info(CSPT& year, CSPT& mon, CSPT& jie, CSPT& jz_mon, CSPT& jz_year); 75 | 76 | // 获取上一个月的年月干支,最后一个参数为当月是否是 立春 77 | void pre_mon_info(CSPT jz_year, CSPT jz_mon, CSPT& jz_year_out, CSPT& jz_mon_out, bool lichun); 78 | 79 | // 给定年干支,返回下一年的年干支和起始月干支 80 | void next_year_info(CSPT jz_year, CSPT& jz_year_out, CSPT& jz_mon_out); 81 | 82 | private: 83 | std::vector difference_jq_{}; // 计算节气的差值数组 84 | std::vector lunar_table_{}; // 农历表数组 85 | }; 86 | 87 | } // namespace csp 88 | 89 | #endif -------------------------------------------------------------------------------- /calendar/src/calendar.cxx: -------------------------------------------------------------------------------- 1 | #include "calendar.h" 2 | #include "cal_sx.h" 3 | #include "cal_table.h" 4 | #include 5 | 6 | #if _WIN32 7 | #include 8 | #endif 9 | 10 | namespace csp { 11 | 12 | Calendar::Calendar() 13 | { 14 | wuhu_[0] = 2; 15 | wuhu_[1] = 4; 16 | wuhu_[2] = 6; 17 | wuhu_[3] = 8; 18 | wuhu_[4] = 0; 19 | wuhu_[5] = 2; 20 | wuhu_[6] = 4; 21 | wuhu_[7] = 6; 22 | wuhu_[8] = 8; 23 | wuhu_[9] = 0; 24 | 25 | qishi_[0] = 0; 26 | qishi_[1] = 2; 27 | qishi_[2] = 4; 28 | qishi_[3] = 6; 29 | qishi_[4] = 8; 30 | qishi_[5] = 0; 31 | qishi_[6] = 2; 32 | qishi_[7] = 4; 33 | qishi_[8] = 6; 34 | qishi_[9] = 8; 35 | } 36 | 37 | std::shared_ptr Calendar::instance(CalendarType type) 38 | { 39 | std::shared_ptr r = nullptr; 40 | switch (type) { 41 | case CalendarType::CAL_TYPE_TABLE: 42 | r = std::make_shared(); 43 | break; 44 | case CalendarType::CAL_TYPE_SXTWL: 45 | r = std::make_shared(); 46 | break; 47 | default: 48 | break; 49 | } 50 | return r; 51 | } 52 | 53 | bool Calendar::check_format_only(const DateTime& dt) 54 | { 55 | if (dt.mon < 1 || dt.mon > 12) { 56 | return false; 57 | } 58 | 59 | int y = dt.year; 60 | int m = dt.mon; 61 | int d = dt.day; 62 | 63 | if (d < 1) { 64 | return false; 65 | } 66 | 67 | if (is_leap(y)) { 68 | if (m == 2) { 69 | if (d > 29) { 70 | return false; 71 | } 72 | } 73 | } else { 74 | if (m == 2) { 75 | if (d > 28) { 76 | return false; 77 | } 78 | } 79 | } 80 | 81 | if (m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) { 82 | if (d > 31) { 83 | return false; 84 | } 85 | } 86 | 87 | if (m == 4 || m == 6 || m == 9 || m == 11) { 88 | if (d > 30) { 89 | return false; 90 | } 91 | } 92 | 93 | int h = dt.hour; 94 | int min = dt.min; 95 | int s = dt.sec; 96 | 97 | if (h > 23 || h < 0) { 98 | return false; 99 | } 100 | if (min > 59 || min < 0) { 101 | return false; 102 | } 103 | if (s > 59 || s < 0) { 104 | return false; 105 | } 106 | 107 | return true; 108 | } 109 | 110 | bool Calendar::is_leap(CSPT year) 111 | { 112 | if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) { 113 | return true; 114 | } 115 | return false; 116 | } 117 | 118 | DateTime Calendar::now() 119 | { 120 | DateTime r{}; 121 | #ifdef _WIN32 122 | SYSTEMTIME nt; 123 | GetLocalTime(&nt); 124 | r.year = nt.wYear; 125 | r.mon = nt.wMonth; 126 | r.day = nt.wDay; 127 | r.hour = nt.wHour; 128 | r.min = nt.wMinute; 129 | r.sec = nt.wSecond; 130 | #else 131 | struct std::tm* nt = nullptr; 132 | std::time_t _otime_t; 133 | std::time(&_otime_t); 134 | nt = std::localtime(&_otime_t); 135 | r.year = nt->tm_year + 1900; 136 | r.mon = nt->tm_mon + 1; 137 | r.day = nt->tm_mday; 138 | r.hour = nt->tm_hour; 139 | r.min = nt->tm_min; 140 | r.sec = nt->tm_sec; 141 | #endif 142 | return r; 143 | } 144 | 145 | CSPT Calendar::mod(CSPT base, CSPT value) 146 | { 147 | return (value % base + base) % base; 148 | } 149 | 150 | bool Calendar::is_same_day(const DateTime& d, const DateTime& p) 151 | { 152 | if (d.year != p.year) { 153 | return false; 154 | } 155 | if (d.mon != p.mon) { 156 | return false; 157 | } 158 | if (d.day != p.day) { 159 | return false; 160 | } 161 | return true; 162 | } 163 | 164 | bool Calendar::is_same_all(const DateTime& d, const DateTime& p) 165 | { 166 | if (!is_same_day(d, p)) { 167 | return false; 168 | } 169 | if (!is_same_time(d, p)) { 170 | return false; 171 | } 172 | return true; 173 | } 174 | 175 | bool Calendar::is_same_time(const DateTime& d, const DateTime& p) 176 | { 177 | if (d.hour != p.hour) { 178 | return false; 179 | } 180 | if (d.min != p.min) { 181 | return false; 182 | } 183 | if (d.sec != p.sec) { 184 | return false; 185 | } 186 | return true; 187 | } 188 | 189 | DateTime Calendar::get_solar() const 190 | { 191 | return solar_; 192 | } 193 | 194 | DateTime Calendar::get_lunar() const 195 | { 196 | return lunar_; 197 | } 198 | 199 | std::array Calendar::get_jq_info() const 200 | { 201 | return jie_; 202 | } 203 | 204 | GanZhi Calendar::get_ganzhi() const 205 | { 206 | return ganzhi; 207 | } 208 | 209 | DateTime::DateTime(CSPT y, CSPT m, CSPT d) 210 | { 211 | year = y; 212 | mon = m; 213 | day = d; 214 | } 215 | 216 | DateTime::DateTime(CSPT y, CSPT m, CSPT d, CSPT h, CSPT mi, CSPT s) 217 | { 218 | year = y; 219 | mon = m; 220 | day = d; 221 | hour = h; 222 | min = mi; 223 | sec = s; 224 | } 225 | 226 | } // namespace csp 227 | -------------------------------------------------------------------------------- /calendar/src/table_data.h: -------------------------------------------------------------------------------- 1 | #ifndef TABLE_DATA_H 2 | #define TABLE_DATA_H 3 | 4 | #include 5 | 6 | void jq_data_init(std::vector& data); 7 | void lunar_data_init(std::vector& data); 8 | 9 | #endif -------------------------------------------------------------------------------- /calendar/xmake.lua: -------------------------------------------------------------------------------- 1 | add_rules("mode.debug", "mode.release") 2 | set_languages("c++11") 3 | add_includedirs(path.join(os.scriptdir(), "include"), {public = true}) 4 | target("calendar") 5 | set_kind("static") 6 | add_files("src/*.cxx") 7 | add_deps("sxtwl") 8 | -------------------------------------------------------------------------------- /config/MSystem.cmake: -------------------------------------------------------------------------------- 1 | # 获取一些常见的本机系统(注意是本机,非交叉编译器的信息)信息 2 | if (UNIX) 3 | execute_process( 4 | COMMAND uname -a 5 | OUTPUT_VARIABLE UNAME_OUTPUT 6 | OUTPUT_STRIP_TRAILING_WHITESPACE 7 | ) 8 | 9 | if(UNAME_OUTPUT MATCHES "x86_64") 10 | set(SYSTEM_ARCH "x86_64") 11 | elseif(UNAME_OUTPUT MATCHES "aarch64") 12 | set(SYSTEM_ARCH "aarch64") 13 | elseif(UNAME_OUTPUT MATCHES "armv7l") 14 | set(SYSTEM_ARCH "armv7l") 15 | elseif(UNAME_OUTPUT MATCHES "i686") 16 | set(SYSTEM_ARCH "i686") 17 | elseif(UNAME_OUTPUT MATCHES "riscv64") 18 | set(SYSTEM_ARCH "riscv64") 19 | else() 20 | set(SYSTEM_ARCH "unknown") 21 | endif() 22 | if(UNAME_OUTPUT MATCHES "alpine" OR UNAME_OUTPUT MATCHES "Alpine") 23 | set(SYSTEM_ARCH "musl_${SYSTEM_ARCH}") 24 | endif() 25 | elseif (WIN32) 26 | # 先调用 ver 命令 27 | execute_process(COMMAND cmd /c ver 28 | OUTPUT_VARIABLE VER_OUTPUT 29 | OUTPUT_STRIP_TRAILING_WHITESPACE) 30 | if(VER_OUTPUT MATCHES "XP") 31 | message(STATUS "Windows XP platform.") 32 | set(SYSTEM_ARCH "x86") 33 | else() 34 | execute_process(COMMAND cmd /c wmic os get osarchitecture 35 | OUTPUT_VARIABLE WMIC_OUTPUT 36 | OUTPUT_STRIP_TRAILING_WHITESPACE) 37 | if(WMIC_OUTPUT MATCHES "64") 38 | set(SYSTEM_ARCH "x86_64") 39 | else() 40 | set(SYSTEM_ARCH "x86") 41 | endif() 42 | endif() 43 | else() 44 | message(FATAL_ERROR "unknow system type.") 45 | endif() 46 | message(STATUS "SYSTEM_ARCH: ${SYSTEM_ARCH}") 47 | -------------------------------------------------------------------------------- /images/csp_qm_sjzpcjzr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taynpg/csp/398e2065ca5a65e05f133930ecd4a44341e88b47/images/csp_qm_sjzpcjzr.png -------------------------------------------------------------------------------- /images/csp_qm_sjzpcjzr_android.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taynpg/csp/398e2065ca5a65e05f133930ecd4a44341e88b47/images/csp_qm_sjzpcjzr_android.jpg -------------------------------------------------------------------------------- /images/ish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taynpg/csp/398e2065ca5a65e05f133930ecd4a44341e88b47/images/ish.png -------------------------------------------------------------------------------- /images/usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taynpg/csp/398e2065ca5a65e05f133930ecd4a44341e88b47/images/usage.png -------------------------------------------------------------------------------- /qimen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(qm LANGUAGES CXX) 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | 7 | if(NOT DEFINED USE_UTF8_ALL) 8 | if (MSVC) 9 | add_compile_options(/source-charset:utf-8) 10 | endif() 11 | if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_SYSTEM_NAME MATCHES "Windows") 12 | MESSAGE(STATUS "qimen Add MinGW Param.") 13 | add_compile_options(-finput-charset=utf-8) 14 | add_compile_options(-fexec-charset=gbk) 15 | endif() 16 | endif() 17 | 18 | set(CMAKE_DEBUG_POSTFIX "d") 19 | include_directories(include) 20 | include_directories(src) 21 | set(SOURCES 22 | src/qimen.cxx src/qm_v1.cxx 23 | src/qm_v2.cxx src/qm_v3.cxx src/qm_v4.cxx 24 | ) 25 | add_library(qm STATIC ${SOURCES}) 26 | target_link_libraries(qm PRIVATE calendar) 27 | target_include_directories(qm PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) -------------------------------------------------------------------------------- /qimen/include/qimen.h: -------------------------------------------------------------------------------- 1 | #ifndef QIMEN_H 2 | #define QIMEN_H 3 | 4 | #include 5 | 6 | namespace csp { 7 | constexpr int gn = 9; 8 | 9 | enum class QimenType { 10 | QM_TYPE_SJ_ZHIRUN = 1, // 时家转盘,超接置润法 11 | QM_TYPE_SJ_YIN, // 时家转盘,阴盘 12 | QM_TYPE_SJ_CHAIBU, // 时家转盘,拆补 13 | QM_TYPE_SJ_MAOSHAN // 时家转盘,茅山 14 | }; 15 | 16 | /* 17 | * 本类中涉及的下标默认内容: 18 | * 以 Pre 结尾的是原始位置: 19 | * 以 Turn 结尾的是旋转位置: 20 | * 以 Re 结尾的是计算结果 21 | * 22 | * 排盘逻辑,无论各派别的定义,排法如何,都基于本程序的原始定义, 23 | * 《排盘前设置好位置和各个符号的初始对应关系》 24 | * 最终生成的结果均已本程序定义的位置排序 25 | * 26 | * ----------------------------------------------------- 27 | * | | | | 28 | * | 位置 4 | 位置 3 | 位置 2 | 29 | * | | | | 30 | * | | | | 31 | * ----------------------------------------------------- 32 | * | | | | 33 | * | 位置 5 | 位置 8 | 位置 1 | 34 | * | | | | 35 | * | | | | 36 | * ----------------------------------------------------- 37 | * | | | | 38 | * | 位置 6 | 位置 7 | 起始位置 0 | 39 | * | | | | 40 | * | | | | 41 | * ----------------------------------------------------- 42 | * 43 | * 44 | * 下面是固定定义,不同的盘需要先设定它们的原始位置和旋转位置: 45 | * -1 0 1 2 3 4 5 6 7 8 46 | * 为空 天蓬 天芮 天冲 天辅 天禽 天心 天柱 天任 天英 47 | * 为空 休门 死门 伤门 杜门 死门 开门 惊门 生门 景门 48 | * 为空 值符 腾蛇 太阴 六合 腾蛇 白虎 玄武 九地 九天 49 | * 为空 坎卦 坤卦 震卦 巽卦 中五 乾卦 兑卦 艮卦 离卦 50 | */ 51 | 52 | struct QimenData { 53 | CSPT ju{}; // 局数 54 | CSPT jiuxr[gn]{}; // 九星的计算结果 55 | CSPT jiuxp[gn]{}; // 九星的原始位置 56 | CSPT jiuxt[gn]{}; // 九星的旋转位置,不足9个的从后向前留空 57 | CSPT pos2gua[gn]{}; // 位置转卦数 58 | CSPT gua2pos[gn]{}; // 卦数转位置 59 | CSPT bamenp[gn]{}; // 八门的原始位置 60 | CSPT bamenr[gn]{}; // 八门的计算结果 61 | CSPT bament[gn]{}; // 八门的旋转位置 62 | CSPT bashenp[gn]{}; // 八神的原始位置 63 | CSPT bashenr[gn]{}; // 八神的计算结果 64 | CSPT tp[gn]{}; // 天盘 65 | CSPT dp[gn]{}; // 地盘 [定义位置:10天干] 66 | CSPT wuxing[gn]{}; // 五行 67 | CSPT jigong{}; // 天禽星寄宫 68 | CSPT maxing{}; // 马星位置 69 | CSPT kongw[2]{}; // 空亡位置 70 | CSPT xunkong[8]{}; // 寻空位置 71 | bool is_yin{}; // 是否是阴遁 72 | CSPT yuan{}; // 三元 0 手动, 1下,2中,3上 73 | bool is_auto{true}; // 是否是自动排局 74 | bool wubuyu{false}; // 是否是五不遇时 75 | CSPT duty{}; // 当值 76 | CSPT jieq{}; // 当日节气 77 | CSPT jiazi{}; // 当日六十甲子 78 | CSPT zhi[12]{}; 79 | CSPT sanhe_[12]{}; // 地支三和 80 | CSPT dzcong_[12]{}; // 地支相冲 81 | }; 82 | 83 | class Qimen 84 | { 85 | public: 86 | Qimen(); 87 | virtual ~Qimen() = default; 88 | 89 | public: 90 | /// @brief 获取六十甲子的下标 91 | /// @param t 天盘下标 92 | /// @param d 地盘下标 93 | /// @return 94 | static CSPT get_jiazi_index(CSPT t, CSPT d); 95 | 96 | /// @brief 获取某个值的位置 97 | /// @param d 数组 98 | /// @param size 数组大小 99 | /// @param value 要寻找的值 100 | /// @return 101 | static CSPT get_index(const CSPT* d, CSPT size, CSPT value); 102 | 103 | /// @brief 获取 奇门 实例 104 | /// @param type 105 | /// @return 106 | static std::shared_ptr instance(QimenType type); 107 | 108 | public: 109 | /// @brief 当某个函数执行失败时,获取错误信息。 110 | /// @return 111 | const char* get_error() const; 112 | 113 | /// @brief 进行排盘 114 | /// @param dt 时间日期 115 | /// @param ju 指定局数。0 为自动,其他需要在 [-9, 9] 的范围。 116 | /// @param ct 使用日历类型 117 | /// @return 118 | virtual bool generate(const DateTime& dt, int ju, CalendarType ct); 119 | 120 | /// @brief 设置信息,并检查。 121 | /// @param dt 日期 122 | /// @param ct 日历类型 123 | /// @return 124 | virtual bool set_and_check(const DateTime& dt, int ju, CalendarType ct); 125 | 126 | /// @brief 设置各个位置上的五行 (金水木火土 数字代表 12345) 127 | virtual void set_wuxing(); 128 | 129 | /// @brief 设置九宫的原始九星位置 130 | virtual void set_jiuxing_pre(); 131 | 132 | /// @brief 设置九星的旋转位置[相对顺序] 133 | virtual void set_jiuxing_turn(); 134 | 135 | /// @brief 设置九宫的数字对应[位置-数字(数字从0开始)] 136 | virtual void set_gong_pos(); 137 | 138 | /// @brief 设置八门的初始位置[位置-八门] 139 | virtual void set_bamen_pre(); 140 | 141 | /// @brief 设置八门的旋转位置 142 | virtual void set_bamen_turn(); 143 | 144 | /// @brief 设置八神的初始位置[位置-八神] 145 | virtual void set_bashen_pre(); 146 | 147 | /// @brief 设置寄宫[固定位置](这里的寄宫是各家自家的卦数) 148 | /// @param gong 卦数 149 | virtual void set_jigong(CSPT gong); 150 | 151 | /// @brief 设置十二地支位置对应 152 | virtual void set_dizhi(); 153 | 154 | virtual std::shared_ptr get_cal() const; 155 | 156 | public: 157 | /// @brief 排地盘 158 | virtual void cal_dipan() = 0; 159 | 160 | /// @brief 计算当值人员 161 | virtual void cal_duty() = 0; 162 | 163 | /// @brief 排九星 164 | virtual void cal_jiuxing() = 0; 165 | 166 | /// @brief 排八门 167 | virtual void cal_bamen() = 0; 168 | 169 | /// @brief 排八神 170 | virtual void cal_bashen() = 0; 171 | 172 | /// @brief 排天盘 173 | virtual void cal_tianpan() = 0; 174 | 175 | /// @brief 排其他信息(如空亡、马星) 176 | virtual void cal_other() = 0; 177 | 178 | public: 179 | QimenData get_result() const; 180 | 181 | protected: 182 | QimenData data_{}; 183 | 184 | DateTime dt_{}; 185 | std::shared_ptr cal_{}; // 日历实例 186 | CalendarType ctype_{}; // 日历的类型 187 | char err_[1024]{}; 188 | }; 189 | } // namespace csp 190 | #endif -------------------------------------------------------------------------------- /qimen/src/qimen.cxx: -------------------------------------------------------------------------------- 1 | #include "qimen.h" 2 | #include "qm_v1.h" 3 | #include "qm_v2.h" 4 | #include "qm_v3.h" 5 | #include "qm_v4.h" 6 | #include 7 | #include 8 | 9 | namespace csp { 10 | 11 | Qimen::Qimen() 12 | { 13 | set_wuxing(); 14 | set_jiuxing_pre(); 15 | set_jiuxing_turn(); 16 | set_gong_pos(); 17 | set_bamen_pre(); 18 | set_bamen_turn(); 19 | set_bashen_pre(); 20 | set_dizhi(); 21 | // 默认寄宫寄 坤二宫 22 | set_jigong(2); 23 | 24 | data_.sanhe_[0] = 8; 25 | data_.sanhe_[1] = 5; 26 | data_.sanhe_[2] = 2; 27 | data_.sanhe_[3] = 2; 28 | data_.sanhe_[4] = 8; 29 | data_.sanhe_[5] = 5; 30 | data_.sanhe_[6] = 2; 31 | data_.sanhe_[7] = 11; 32 | data_.sanhe_[8] = 8; 33 | data_.sanhe_[9] = 5; 34 | data_.sanhe_[10] = 2; 35 | data_.sanhe_[11] = 11; 36 | 37 | data_.dzcong_[8] = 2; 38 | data_.dzcong_[5] = 11; 39 | data_.dzcong_[2] = 8; 40 | data_.dzcong_[2] = 8; 41 | data_.dzcong_[11] = 5; 42 | } 43 | 44 | CSPT Qimen::get_jiazi_index(CSPT t, CSPT d) 45 | { 46 | int n = d; 47 | for (int i = 0; i < 5; ++i) { 48 | if ((n % 10) == t) { 49 | break; 50 | } 51 | n += 12; 52 | } 53 | return n; 54 | } 55 | 56 | CSPT Qimen::get_index(const CSPT* d, CSPT size, CSPT value) 57 | { 58 | if (!d) { 59 | return -1; 60 | } 61 | 62 | int n = -1; 63 | for (int i = 0; i < size; ++i) { 64 | if (d[i] == value) { 65 | n = i; 66 | break; 67 | } 68 | } 69 | return n; 70 | } 71 | 72 | std::shared_ptr Qimen::instance(QimenType type) 73 | { 74 | std::shared_ptr re = nullptr; 75 | switch (type) { 76 | case QimenType::QM_TYPE_SJ_ZHIRUN: 77 | re = std::make_shared(); 78 | break; 79 | case QimenType::QM_TYPE_SJ_YIN: 80 | re = std::make_shared(); 81 | break; 82 | case QimenType::QM_TYPE_SJ_CHAIBU: 83 | re = std::make_shared(); 84 | break; 85 | case QimenType::QM_TYPE_SJ_MAOSHAN: 86 | re = std::make_shared(); 87 | break; 88 | default: 89 | break; 90 | } 91 | return re; 92 | } 93 | 94 | const char* Qimen::get_error() const 95 | { 96 | return err_; 97 | } 98 | 99 | bool Qimen::generate(const DateTime& dt, int ju, CalendarType ct) 100 | { 101 | return false; 102 | } 103 | 104 | bool Qimen::set_and_check(const DateTime& dt, int ju, CalendarType ct) 105 | { 106 | ctype_ = ct; 107 | cal_ = Calendar::instance(ctype_); 108 | if (!cal_->check_format_only(dt)) { 109 | std::snprintf(err_, sizeof(err_), "%s", "日期不在支持的范围内。"); 110 | return false; 111 | } 112 | if (ju < -9 || ju > 9) { 113 | std::snprintf(err_, sizeof(err_), "%s", "局数设定不在[-9, 9]范围内。"); 114 | return false; 115 | } 116 | dt_ = dt; 117 | data_.ju = std::abs(ju); 118 | data_.is_yin = (ju < 0 ? true : false); 119 | return true; 120 | } 121 | 122 | void Qimen::set_wuxing() 123 | { 124 | data_.wuxing[0] = 1; 125 | data_.wuxing[1] = 1; 126 | data_.wuxing[2] = 5; 127 | data_.wuxing[3] = 4; 128 | data_.wuxing[4] = 3; 129 | data_.wuxing[5] = 3; 130 | data_.wuxing[6] = 5; 131 | data_.wuxing[7] = 2; 132 | data_.wuxing[8] = 5; 133 | } 134 | 135 | void Qimen::set_jiuxing_pre() 136 | { 137 | data_.jiuxp[0] = 5; 138 | data_.jiuxp[1] = 6; 139 | data_.jiuxp[2] = 1; 140 | data_.jiuxp[3] = 8; 141 | data_.jiuxp[4] = 3; 142 | data_.jiuxp[5] = 2; 143 | data_.jiuxp[6] = 7; 144 | data_.jiuxp[7] = 0; 145 | data_.jiuxp[8] = 4; 146 | } 147 | 148 | void Qimen::set_jiuxing_turn() 149 | { 150 | data_.jiuxt[0] = 0; 151 | data_.jiuxt[1] = 7; 152 | data_.jiuxt[2] = 2; 153 | data_.jiuxt[3] = 3; 154 | data_.jiuxt[4] = 8; 155 | data_.jiuxt[5] = 1; 156 | data_.jiuxt[6] = 6; 157 | data_.jiuxt[7] = 5; 158 | } 159 | 160 | void Qimen::set_gong_pos() 161 | { 162 | // 定义位置从 0 开始分别对应卦序 163 | data_.pos2gua[0] = 5; 164 | data_.pos2gua[1] = 6; 165 | data_.pos2gua[2] = 1; 166 | data_.pos2gua[3] = 8; 167 | data_.pos2gua[4] = 3; 168 | data_.pos2gua[5] = 2; 169 | data_.pos2gua[6] = 7; 170 | data_.pos2gua[7] = 0; 171 | data_.pos2gua[8] = 4; 172 | 173 | // gua2pos_ 就是后天八卦的顺序数和定义位置的对照。 174 | for (int i = 0; i < 9; ++i) { 175 | data_.gua2pos[data_.pos2gua[i]] = i; 176 | } 177 | } 178 | 179 | void Qimen::set_bamen_pre() 180 | { 181 | data_.bamenp[0] = 5; 182 | data_.bamenp[1] = 6; 183 | data_.bamenp[2] = 1; 184 | data_.bamenp[3] = 8; 185 | data_.bamenp[4] = 3; 186 | data_.bamenp[5] = 2; 187 | data_.bamenp[6] = 7; 188 | data_.bamenp[7] = 0; 189 | data_.bamenp[8] = 4; 190 | } 191 | 192 | void Qimen::set_bamen_turn() 193 | { 194 | data_.bament[0] = 0; 195 | data_.bament[1] = 7; 196 | data_.bament[2] = 2; 197 | data_.bament[3] = 3; 198 | data_.bament[4] = 8; 199 | data_.bament[5] = 1; 200 | data_.bament[6] = 6; 201 | data_.bament[7] = 5; 202 | } 203 | 204 | void Qimen::set_bashen_pre() 205 | { 206 | data_.bashenp[0] = 5; 207 | data_.bashenp[1] = 6; 208 | data_.bashenp[2] = 1; 209 | data_.bashenp[3] = 8; 210 | data_.bashenp[4] = 3; 211 | data_.bashenp[5] = 2; 212 | data_.bashenp[6] = 7; 213 | data_.bashenp[7] = 0; 214 | data_.bashenp[8] = 4; 215 | } 216 | 217 | void Qimen::set_jigong(CSPT gong) 218 | { 219 | // 这里减 1 是取索引 220 | int n = gong - 1; 221 | // 这里要把寄宫转成位置 222 | data_.jigong = data_.gua2pos[n]; 223 | } 224 | 225 | void Qimen::set_dizhi() 226 | { 227 | data_.zhi[0] = 7; 228 | data_.zhi[1] = 6; 229 | data_.zhi[2] = 6; 230 | data_.zhi[3] = 5; 231 | data_.zhi[4] = 4; 232 | data_.zhi[5] = 4; 233 | data_.zhi[6] = 3; 234 | data_.zhi[7] = 2; 235 | data_.zhi[8] = 2; 236 | data_.zhi[9] = 1; 237 | data_.zhi[10] = 0; 238 | data_.zhi[11] = 0; 239 | } 240 | 241 | std::shared_ptr Qimen::get_cal() const 242 | { 243 | return cal_; 244 | } 245 | 246 | QimenData Qimen::get_result() const 247 | { 248 | return data_; 249 | } 250 | 251 | } // namespace csp 252 | -------------------------------------------------------------------------------- /qimen/src/qm_v1.cxx: -------------------------------------------------------------------------------- 1 | #include "qm_v1.h" 2 | #include 3 | 4 | namespace csp { 5 | QimenV1::QimenV1() 6 | { 7 | // 下标 0 指小寒,即从小寒开始向后排列。 8 | juqi_[0] = 2851; 9 | juqi_[1] = 3961; 10 | juqi_[2] = 8521; 11 | juqi_[3] = 9631; 12 | juqi_[4] = 1741; 13 | juqi_[5] = 3961; 14 | juqi_[6] = 4171; 15 | juqi_[7] = 5281; 16 | juqi_[8] = 4171; 17 | juqi_[9] = 5281; 18 | juqi_[10] = 6391; 19 | juqi_[11] = 9360; 20 | juqi_[12] = 8250; 21 | juqi_[13] = 7140; 22 | juqi_[14] = 2580; 23 | juqi_[15] = 1470; 24 | juqi_[16] = 9360; 25 | juqi_[17] = 7140; 26 | juqi_[18] = 6930; 27 | juqi_[19] = 5820; 28 | juqi_[20] = 6930; 29 | juqi_[21] = 5820; 30 | juqi_[22] = 4710; 31 | juqi_[23] = 1741; 32 | 33 | wby_[0] = 6; 34 | wby_[1] = 17; 35 | wby_[2] = 28; 36 | wby_[3] = 39; 37 | wby_[4] = 50; 38 | wby_[5] = 1; 39 | wby_[6] = 12; 40 | wby_[7] = 33; 41 | wby_[8] = 44; 42 | wby_[9] = 55; 43 | } 44 | 45 | bool QimenV1::generate(const DateTime& dt, int ju, CalendarType ct) 46 | { 47 | if (!Qimen::set_and_check(dt, ju, ct)) { 48 | return false; 49 | } 50 | if (!cal_->generate(dt_)) { 51 | return false; 52 | } 53 | if (data_.ju == 0 && !cal_ju(dt)) { 54 | return false; 55 | } 56 | 57 | cal_dipan(); 58 | cal_duty(); 59 | cal_jiuxing(); 60 | cal_bamen(); 61 | cal_bashen(); 62 | cal_tianpan(); 63 | cal_other(); 64 | 65 | return true; 66 | } 67 | 68 | void QimenV1::cal_dipan() 69 | { 70 | // 所谓的几局,就是甲子戊居于第几宫 71 | int s = Calendar::mod(9, data_.ju - 1); 72 | data_.dp[data_.gua2pos[s]] = 4; 73 | int nk = data_.is_yin ? -1 : 1; 74 | 75 | for (int i = 0; i < 5; ++i) { 76 | data_.dp[data_.gua2pos[Calendar::mod(9, s += nk)]] = 5 + i; 77 | } 78 | for (int i = 0; i < 3; ++i) { 79 | data_.dp[data_.gua2pos[Calendar::mod(9, s += nk)]] = 3 - i; 80 | } 81 | 82 | // 判断是否是 五不遇时 83 | int hg = cal_->get_ganzhi().hg; 84 | int hz = cal_->get_ganzhi().hz; 85 | int i = Qimen::get_jiazi_index(hg, hz); 86 | if (wby_[cal_->get_ganzhi().dg] == i) { 87 | data_.wubuyu = true; 88 | } else { 89 | data_.wubuyu = false; 90 | } 91 | } 92 | 93 | void QimenV1::cal_duty() 94 | { 95 | // 六十甲子 96 | int hi = Qimen::get_jiazi_index(cal_->get_ganzhi().hg, cal_->get_ganzhi().hz); 97 | // 查看旬头遁甲位置 98 | int gi = (hi / 10) + 4; 99 | // 这里算出来的值是场地位置 100 | data_.duty = get_index(data_.dp, 9, gi); 101 | } 102 | 103 | void QimenV1::cal_jiuxing() 104 | { 105 | // 先查验当前的局是否为伏吟 106 | if (cal_->get_ganzhi().hg == 0) { 107 | for (int i = 0; i < 9; ++i) { 108 | data_.jiuxr[i] = data_.jiuxp[i]; 109 | data_.bamenr[i] = data_.bamenp[i]; 110 | } 111 | return; 112 | } 113 | // 时辰天干在地盘的位置 114 | int s = get_index(data_.dp, 9, cal_->get_ganzhi().hg); 115 | // 如果这个位置在中宫,那么从寄宫开始 116 | s = (s == 8 ? data_.jigong : s); 117 | 118 | int nx = data_.jiuxp[data_.duty]; 119 | // 如果当前的值符为天禽星,那么也归为原寄宫星 120 | nx = (nx == 4 ? data_.jiuxp[data_.jigong] : nx); 121 | data_.jiuxr[s] = nx; 122 | 123 | // 查找当前的九星的起始相对位置 124 | int nt = get_index(data_.jiuxt, 8, nx); 125 | for (int i = 0; i < 8; ++i) { 126 | data_.jiuxr[Calendar::mod(8, --s)] = data_.jiuxt[Calendar::mod(8, ++nt)]; 127 | } 128 | data_.jiuxr[8] = 4; 129 | } 130 | 131 | void QimenV1::cal_bamen() 132 | { 133 | // 查看当前旬头六仪 134 | int hi = Qimen::get_jiazi_index(cal_->get_ganzhi().hg, cal_->get_ganzhi().hz); 135 | // 查看当前时辰距离符头有几跳 136 | int dif = hi - (hi / 10) * 10; 137 | 138 | int nk = data_.is_yin ? -1 : 1; 139 | 140 | /* 141 | bm_pre_ 中仅有 8 个数据,当值符值使位置在中宫8的时候,转成寄宫 142 | 但是转的时候不从寄宫开始转 143 | */ 144 | int s = data_.duty; 145 | s = (s == 8 ? data_.jigong : s); 146 | 147 | int gi = data_.pos2gua[data_.duty]; 148 | for (int i = 0; i < dif; ++i) { 149 | gi = Calendar::mod(9, gi += nk); 150 | } 151 | int np = data_.gua2pos[gi]; 152 | // 如果门转到了中宫,也是按照寄宫处理。 153 | np = (np == 8 ? data_.jigong : np); 154 | 155 | int mi = get_index(data_.bament, 8, data_.bamenp[s]); 156 | for (int i = 0; i < 8; ++i, --np, ++mi) { 157 | data_.bamenr[Calendar::mod(8, np)] = data_.bament[Calendar::mod(8, mi)]; 158 | } 159 | } 160 | 161 | void QimenV1::cal_bashen() 162 | { 163 | int nx = data_.jiuxp[data_.duty]; 164 | nx = (nx == 4 ? data_.jiuxp[data_.jigong] : nx); 165 | // 看看值符被转到哪里了 166 | int s = get_index(data_.jiuxr, 9, nx); 167 | int nk = data_.is_yin ? 1 : -1; 168 | for (int i = 0; i < 9; ++i, s += nk) { 169 | if (i == 4) { 170 | ++i; 171 | } 172 | data_.bashenr[Calendar::mod(8, s)] = i; 173 | } 174 | } 175 | 176 | void QimenV1::cal_tianpan() 177 | { 178 | // 当前九星宫位的天盘就是:当前星原来宫位中的地盘 179 | for (int i = 0; i < 8; ++i) { 180 | data_.tp[i] = data_.dp[data_.gua2pos[data_.jiuxr[i]]]; 181 | } 182 | data_.tp[8] = data_.dp[8]; 183 | } 184 | 185 | void QimenV1::cal_other() 186 | { 187 | auto gen = [this](CSPT g, CSPT z, CSPT& a, CSPT& b) { 188 | int j = Qimen::get_jiazi_index(g, z); 189 | const auto& r = cal_xunkong(j); 190 | a = r.first; 191 | b = r.second; 192 | }; 193 | 194 | gen(cal_->get_ganzhi().yg, cal_->get_ganzhi().yz, data_.xunkong[0], data_.xunkong[1]); 195 | gen(cal_->get_ganzhi().mg, cal_->get_ganzhi().mz, data_.xunkong[2], data_.xunkong[3]); 196 | gen(cal_->get_ganzhi().dg, cal_->get_ganzhi().dz, data_.xunkong[4], data_.xunkong[5]); 197 | gen(cal_->get_ganzhi().hg, cal_->get_ganzhi().hz, data_.xunkong[6], data_.xunkong[7]); 198 | 199 | data_.kongw[0] = data_.zhi[data_.xunkong[6]]; 200 | data_.kongw[1] = data_.zhi[data_.xunkong[7]]; 201 | data_.maxing = data_.zhi[data_.dzcong_[data_.sanhe_[cal_->get_ganzhi().hz]]]; 202 | } 203 | 204 | bool QimenV1::inference() 205 | { 206 | year_datas_.clear(); 207 | 208 | CSPT start = 22; 209 | CSPT dif = 0; 210 | CSPT jiazi = 0; 211 | CSPT tem = 0; 212 | 213 | DateTime pdx(dt_.year - 1, 12, 1, 12, 0, 0); 214 | DateTime dx(dt_.year, 12, 1, 12, 0, 0); 215 | DateTime mz(dt_.year, 6, 6, 12, 0, 0); 216 | DateTime dt{}; 217 | 218 | DateTime t; 219 | DateTime c; 220 | 221 | if (!cur_month_jq(pdx, t, jiazi, dif)) { 222 | return false; 223 | } 224 | c = t; 225 | // 保存大雪的三元 226 | save_part(c, start, jiazi, -1, 15 - dif); 227 | 228 | if (dif < 9) { 229 | start = Calendar::mod(24, ++start); 230 | } 231 | 232 | // 保存大雪到芒种 233 | save_part(c, start, jiazi, 10, 300); 234 | if (!cur_month_jq(mz, t, tem, dif)) { 235 | return false; 236 | } 237 | 238 | dt = c; 239 | cal_->pre_day(dt, 1); 240 | dif = std::abs(cal_->days_difference(dt, t)); 241 | save_part(c, start, jiazi, -1, 14); 242 | if (dif < 9) { 243 | start = Calendar::mod(24, ++start); 244 | } 245 | 246 | save_part(c, start, jiazi, 22, 300); 247 | if (!cur_month_jq(dx, t, tem, dif)) { 248 | return false; 249 | } 250 | 251 | dt = c; 252 | cal_->pre_day(dt, 1); 253 | dif = std::abs(cal_->days_difference(dt, t)); 254 | save_part(c, start, jiazi, -1, 14); 255 | if (dif < 9) { 256 | start = Calendar::mod(24, ++start); 257 | } 258 | save_part(c, start, jiazi, -1, 60); 259 | return true; 260 | } 261 | 262 | bool QimenV1::search_day(const DateTime& datetime, OneDay& o) 263 | { 264 | bool find = false; 265 | for (const auto& item : year_datas_) { 266 | if (Calendar::is_same_day(item.dt, datetime)) { 267 | o = item; 268 | find = true; 269 | break; 270 | } 271 | } 272 | return find; 273 | } 274 | 275 | bool QimenV1::cur_month_jq(const DateTime& dt, DateTime& jie, CSPT& jiazi, CSPT& dif) 276 | { 277 | auto tcal = Calendar::instance(ctype_); 278 | if (!tcal->generate(dt)) { 279 | return false; 280 | } 281 | auto jqs = tcal->get_jq_info(); 282 | jie = jqs[2].dt; 283 | 284 | if (!tcal->generate(jie)) { 285 | return false; 286 | } 287 | jiazi = get_jiazi_index(tcal->get_ganzhi().dg, tcal->get_ganzhi().dz); 288 | CSPT ft = (jiazi / 15) * 15; 289 | dif = jiazi - ft; 290 | if (dif < 0) { 291 | dif = -dif; 292 | } 293 | return true; 294 | } 295 | 296 | void QimenV1::save_part(DateTime& sdt, CSPT& upper, CSPT& jiazi, CSPT pur, CSPT days) 297 | { 298 | int cy = 0; 299 | upper = Calendar::mod(24, upper); 300 | for (int i = 0; i < days; ++i, ++cy) { 301 | year_datas_.emplace_back(OneDay{sdt, upper, jiazi}); 302 | cal_->next_day(sdt, 1); 303 | jiazi = Calendar::mod(60, ++jiazi); 304 | if (cy == 15) { 305 | upper = Calendar::mod(24, ++upper); 306 | if (upper == pur) { 307 | break; 308 | } 309 | cy = 0; 310 | } 311 | } 312 | } 313 | 314 | std::pair QimenV1::cal_xunkong(CSPT jiazi) 315 | { 316 | int ka = ((jiazi / 10) * 10 + 10) % 12; 317 | int kb = ((jiazi / 10) * 10 + 11) % 12; 318 | return std::make_pair(ka, kb); 319 | } 320 | 321 | bool QimenV1::cal_ju(const DateTime& dt) 322 | { 323 | if (data_.ju != 0) { 324 | data_.yuan = 0; 325 | return true; 326 | } 327 | 328 | inference(); 329 | OneDay o; 330 | if (!search_day(dt, o)) { 331 | return false; 332 | } 333 | 334 | data_.jiazi = o.ganzhi; 335 | data_.jieq = o.jq; 336 | 337 | int tv = juqi_[o.jq]; 338 | if ((tv % 10) == 1) { 339 | data_.is_yin = false; 340 | } else { 341 | data_.is_yin = true; 342 | } 343 | 344 | int tv2 = (o.ganzhi % 15) / 5; 345 | if (tv2 == 0) { 346 | data_.yuan = 3; 347 | data_.ju = tv / 1000; 348 | } else if (tv2 == 1) { 349 | data_.yuan = 2; 350 | data_.ju = (tv / 100) % 10; 351 | } else { 352 | data_.yuan = 1; 353 | data_.ju = (tv / 10) % 10; 354 | } 355 | return true; 356 | } 357 | 358 | OneDay::OneDay(const DateTime& adt, CSPT ajq, CSPT agz) 359 | { 360 | dt = adt; 361 | jq = ajq; 362 | ganzhi = agz; 363 | } 364 | } // namespace csp -------------------------------------------------------------------------------- /qimen/src/qm_v1.h: -------------------------------------------------------------------------------- 1 | #ifndef QM_SHIJIA_CHAOJIEZHIRUN 2 | #define QM_SHIJIA_CHAOJIEZHIRUN 3 | 4 | #include "qimen.h" 5 | #include 6 | #include 7 | 8 | namespace csp { 9 | // V1 : 转盘 时家 超接置润法 10 | 11 | /* 12 | * 转盘置润法的排盘方法: 13 | * 一旬十个时辰、由一个值符看管、九星中的一个星。 14 | * 1.地盘的排法(超接法定遁) 15 | * 2.值符就是:当前时干旬头甲,在地盘哪个宫,这个宫的原始星就是值符。 16 | * 3.值使同值符相同的找法。 17 | * 4.转动星盘:值符随时干,即值符放在时干的位置。 18 | * 5.转动门盘:值使随时支,即值使放在从旬头按阳顺阴逆的方法排列。 19 | * 20 | * */ 21 | 22 | struct OneDay { 23 | OneDay() = default; 24 | OneDay(const DateTime& adt, CSPT ajq, CSPT agz); 25 | DateTime dt{}; 26 | CSPT jq{}; 27 | CSPT ganzhi{}; 28 | }; 29 | 30 | class QimenV1 : public Qimen 31 | { 32 | public: 33 | QimenV1(); 34 | virtual ~QimenV1() = default; 35 | 36 | public: 37 | // 排盘 38 | bool generate(const DateTime& dt, int ju, CalendarType ct) override; 39 | 40 | /// @brief 排地盘 41 | void cal_dipan() override; 42 | 43 | /// @brief 计算当值人员 44 | void cal_duty() override; 45 | 46 | /// @brief 排九星 47 | void cal_jiuxing() override; 48 | 49 | /// @brief 排八门 50 | void cal_bamen() override; 51 | 52 | /// @brief 排八神 53 | void cal_bashen() override; 54 | 55 | /// @brief 排天盘 56 | void cal_tianpan() override; 57 | 58 | /// @brief 排其他信息(如空亡、马星) 59 | void cal_other() override; 60 | 61 | private: 62 | // 推演一年的日历 63 | bool inference(); 64 | 65 | // 在一年的日历中查找当天的信息 66 | bool search_day(const DateTime& datetime, OneDay& o); 67 | 68 | // 获取当月节气信息 69 | bool cur_month_jq(const DateTime& dt, DateTime& jie, CSPT& jiazi, CSPT& dif); 70 | 71 | // 保存某段范围的日期信息 72 | void save_part(DateTime& sdt, CSPT& upper, CSPT& jiazi, CSPT pur, CSPT days); 73 | 74 | // 获取给定甲子的两个寻空 75 | std::pair cal_xunkong(CSPT jiazi); 76 | 77 | private: 78 | bool cal_ju(const DateTime& dt); 79 | 80 | protected: 81 | CSPT juqi_[24]{}; 82 | 83 | std::vector year_datas_{}; 84 | std::unordered_map wby_{}; 85 | }; 86 | } // namespace csp 87 | 88 | #endif -------------------------------------------------------------------------------- /qimen/src/qm_v2.cxx: -------------------------------------------------------------------------------- 1 | #include "qm_v2.h" 2 | 3 | namespace csp { 4 | 5 | QimenV2::QimenV2() 6 | { 7 | } 8 | 9 | QimenV2::~QimenV2() 10 | { 11 | } 12 | 13 | bool QimenV2::generate(const DateTime& dt, int ju, CalendarType ct) 14 | { 15 | if (!Qimen::set_and_check(dt, ju, ct)) { 16 | return false; 17 | } 18 | if (!cal_->generate(dt_)) { 19 | return false; 20 | } 21 | if (data_.ju == 0 && !cal_ju(dt)) { 22 | return false; 23 | } 24 | 25 | cal_dipan(); 26 | cal_duty(); 27 | cal_jiuxing(); 28 | cal_bamen(); 29 | cal_bashen(); 30 | cal_tianpan(); 31 | cal_other(); 32 | 33 | return true; 34 | } 35 | 36 | bool QimenV2::cal_ju(const DateTime& dt) 37 | { 38 | auto tcal = Calendar::instance(ctype_); 39 | if (!tcal->generate(dt)) { 40 | return false; 41 | } 42 | // 年支数字 43 | int yz = cal_->get_ganzhi().yz + 1; 44 | // 农历月日 45 | int lm = cal_->get_lunar().mon; 46 | int ld = cal_->get_lunar().day; 47 | // 时辰数字 48 | int hm = cal_->get_ganzhi().hz + 1; 49 | 50 | int sum = yz + lm + ld + hm; 51 | data_.ju = sum % 9; 52 | data_.ju = (data_.ju == 0 ? 9 : data_.ju); 53 | 54 | // 判断阴阳遁 55 | // *************** 冬至 56 | DateTime dz(dt.year, 12, 12, 12, 0, 0); 57 | if (!tcal->generate(dz)) { 58 | return false; 59 | } 60 | dz = cal_->get_jq_info()[3].dt; 61 | // *************** 夏至 62 | DateTime xz(dt.year, 6, 15, 12, 0, 0); 63 | if (!tcal->generate(xz)) { 64 | return false; 65 | } 66 | xz = cal_->get_jq_info()[3].dt; 67 | 68 | auto da = cal_->calsecs_by_all(dt, xz); 69 | auto db = cal_->calsecs_by_all(dt, dz); 70 | 71 | // --- 阳遁 --- 夏至 --- 阴遁 --- 冬至 --- 阳遁 72 | if (da > 0 && db <= 0) { 73 | data_.is_yin = true; 74 | } else { 75 | data_.is_yin = false; 76 | } 77 | return true; 78 | } 79 | 80 | } // namespace csp 81 | -------------------------------------------------------------------------------- /qimen/src/qm_v2.h: -------------------------------------------------------------------------------- 1 | #ifndef QM_V2_HEADER 2 | #define QM_V2_HEADER 3 | 4 | #include "qm_v1.h" 5 | 6 | namespace csp { 7 | // V2 : 转盘 时家 阴盘 8 | class QimenV2 : public QimenV1 9 | { 10 | public: 11 | QimenV2(); 12 | ~QimenV2() override; 13 | 14 | public: 15 | // 排盘 16 | bool generate(const DateTime& dt, int ju, CalendarType ct) override; 17 | 18 | private: 19 | bool cal_ju(const DateTime& dt); 20 | }; 21 | } // namespace csp 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /qimen/src/qm_v3.cxx: -------------------------------------------------------------------------------- 1 | #include "qm_v3.h" 2 | 3 | namespace csp { 4 | 5 | QimenV3::QimenV3() 6 | { 7 | } 8 | 9 | QimenV3::~QimenV3() 10 | { 11 | } 12 | 13 | bool QimenV3::generate(const DateTime& dt, int ju, CalendarType ct) 14 | { 15 | if (!Qimen::set_and_check(dt, ju, ct)) { 16 | return false; 17 | } 18 | if (!cal_->generate(dt_)) { 19 | return false; 20 | } 21 | if (data_.ju == 0 && !cal_ju(dt)) { 22 | return false; 23 | } 24 | 25 | cal_dipan(); 26 | cal_duty(); 27 | cal_jiuxing(); 28 | cal_bamen(); 29 | cal_bashen(); 30 | cal_tianpan(); 31 | cal_other(); 32 | 33 | return true; 34 | } 35 | 36 | bool QimenV3::cal_ju(const DateTime& dt) 37 | { 38 | if (data_.ju != 0) { 39 | data_.yuan = 0; 40 | return true; 41 | } 42 | 43 | int jiazi = Qimen::get_jiazi_index(cal_->get_ganzhi().dg, cal_->get_ganzhi().dz); 44 | // 符头只有两个,甲 或者 己 45 | int ft = jiazi - jiazi % 5; 46 | // 看地支 47 | // 0 3 6 9 上元 48 | // 2 5 8 11 中元 49 | // 1 4 7 10 下元 50 | int zi = ft % 12; 51 | 52 | // 直接找出当月的节气信息,看在哪个节气的后面 53 | auto jiea = cal_->get_jq_info()[2].dt; 54 | auto jieb = cal_->get_jq_info()[3].dt; 55 | 56 | auto df1 = cal_->calsecs_by_all(dt_, jiea); 57 | auto df2 = cal_->calsecs_by_all(dt_, jieb); 58 | 59 | int r = 0; 60 | if (df1 >= 0 && df2 < 0) { 61 | data_.jieq = cal_->get_jq_info()[2].index; 62 | } else if (df1 < 0) { 63 | data_.jieq = Calendar::mod(24, cal_->get_jq_info()[2].index - 1); 64 | } else { 65 | data_.jieq = cal_->get_jq_info()[3].index; 66 | } 67 | r = juqi_[data_.jieq]; 68 | data_.is_yin = (r % 10 == 1 ? false : true); 69 | 70 | if (zi % 3 == 0) { 71 | data_.yuan = 3; 72 | data_.ju = r / 1000; 73 | } 74 | if (zi % 3 == 1) { 75 | data_.yuan = 1; 76 | data_.ju = (r / 10) % 10; 77 | } 78 | if (zi % 3 == 2) { 79 | data_.yuan = 2; 80 | data_.ju = (r / 100) % 10; 81 | } 82 | 83 | return true; 84 | } 85 | } // namespace csp -------------------------------------------------------------------------------- /qimen/src/qm_v3.h: -------------------------------------------------------------------------------- 1 | #ifndef QM_V3_HEADER 2 | #define QM_V3_HEADER 3 | 4 | #include "qm_v1.h" 5 | 6 | namespace csp { 7 | // V3 : 转盘 时家 拆补法 8 | class QimenV3 : public QimenV1 9 | { 10 | public: 11 | QimenV3(); 12 | ~QimenV3() override; 13 | 14 | public: 15 | // 排盘 16 | bool generate(const DateTime& dt, int ju, CalendarType ct) override; 17 | 18 | private: 19 | bool cal_ju(const DateTime& dt); 20 | }; 21 | } // namespace csp 22 | 23 | #endif -------------------------------------------------------------------------------- /qimen/src/qm_v4.cxx: -------------------------------------------------------------------------------- 1 | #include "qm_v4.h" 2 | 3 | namespace csp { 4 | 5 | QimenV4::QimenV4() 6 | { 7 | } 8 | 9 | QimenV4::~QimenV4() 10 | { 11 | } 12 | 13 | bool QimenV4::generate(const DateTime& dt, int ju, CalendarType ct) 14 | { 15 | if (!Qimen::set_and_check(dt, ju, ct)) { 16 | return false; 17 | } 18 | if (!cal_->generate(dt_)) { 19 | return false; 20 | } 21 | if (data_.ju == 0 && !cal_ju(dt)) { 22 | return false; 23 | } 24 | 25 | cal_dipan(); 26 | cal_duty(); 27 | cal_jiuxing(); 28 | cal_bamen(); 29 | cal_bashen(); 30 | cal_tianpan(); 31 | cal_other(); 32 | 33 | return true; 34 | } 35 | 36 | bool QimenV4::cal_ju(const DateTime& dt) 37 | { 38 | auto jiea = cal_->get_jq_info()[2].dt; 39 | auto jieb = cal_->get_jq_info()[3].dt; 40 | 41 | // --- 节气1 --- 时间 --- 节气2 ---- 42 | auto df1 = cal_->calsecs_by_all(dt_, jiea); 43 | auto df2 = cal_->calsecs_by_all(dt_, jieb); 44 | 45 | JieQi jieqi; 46 | if (df1 < 0) { 47 | jieqi = cal_->get_jq_info()[1]; 48 | } else if (df1 >= 0 && df2 < 0) { 49 | jieqi = cal_->get_jq_info()[2]; 50 | } else { 51 | jieqi = cal_->get_jq_info()[3]; 52 | } 53 | data_.yuan = cal_yuan(jieqi.dt, dt_); 54 | data_.jieq = jieqi.index; 55 | 56 | if (data_.ju != 0) { 57 | return true; 58 | } 59 | 60 | int r = juqi_[data_.jieq]; 61 | data_.is_yin = (r % 10 == 1 ? false : true); 62 | 63 | if (data_.yuan == 3) { 64 | data_.ju = r / 1000; 65 | } else if (data_.yuan == 2) { 66 | data_.ju = (r / 100) % 10; 67 | } else { 68 | data_.ju = (r / 10) % 10; 69 | } 70 | return true; 71 | } 72 | 73 | int QimenV4::cal_yuan(const DateTime& jie, const DateTime& dt) 74 | { 75 | constexpr CSPLT five_day = 3600 * 24 * 5; 76 | // 判断是否在节气后的5天内 77 | auto v1 = cal_->cal_new_date(jie, five_day); 78 | auto dif = cal_->calsecs_by_all(dt, v1); 79 | if (dif < 0) { 80 | return 3; 81 | } 82 | // 判断是否在节气后的10天内 83 | auto v2 = cal_->cal_new_date(jie, five_day * 2); 84 | dif = cal_->calsecs_by_all(dt, v2); 85 | if (dif < 0) { 86 | return 2; 87 | } else { 88 | return 1; 89 | } 90 | } 91 | 92 | } // namespace csp -------------------------------------------------------------------------------- /qimen/src/qm_v4.h: -------------------------------------------------------------------------------- 1 | #ifndef QM_V4_HEADER 2 | #define QM_V4_HEADER 3 | 4 | #include "qm_v1.h" 5 | 6 | namespace csp { 7 | // V4 : 转盘 时家 茅山法 8 | class QimenV4 : public QimenV1 9 | { 10 | public: 11 | QimenV4(); 12 | ~QimenV4() override; 13 | 14 | public: 15 | // 排盘 16 | bool generate(const DateTime& dt, int ju, CalendarType ct) override; 17 | 18 | private: 19 | bool cal_ju(const DateTime& dt); 20 | int cal_yuan(const DateTime& jie, const DateTime& dt); 21 | }; 22 | } // namespace csp 23 | 24 | #endif -------------------------------------------------------------------------------- /src/ColorConsole.hpp: -------------------------------------------------------------------------------- 1 | // Based on https://gitee.com/whatitis/ColorfulConsoleIO/ modification 2 | 3 | #include 4 | #include 5 | 6 | #if defined(_WIN32) 7 | #include 8 | #endif // OS_TYPE_WINDOWS_CC 9 | 10 | // Enum class for console text color 11 | enum class ConsoleColor { 12 | Green, 13 | Red, 14 | Blue, 15 | White, 16 | Black, 17 | Yellow, 18 | Purple, 19 | Gray, 20 | Cyan, 21 | None, 22 | GreenIntensity, 23 | RedIntensity, 24 | BlueIntensity, 25 | WhiteIntensity, 26 | BlackIntensity, 27 | YellowIntensity, 28 | PurpleIntensity, 29 | GrayIntensity, 30 | CyanIntensity 31 | }; 32 | 33 | // Enum class for console background color 34 | enum class ConsoleBackgroundColor { 35 | Green, 36 | Red, 37 | Blue, 38 | White, 39 | Black, 40 | Yellow, 41 | Purple, 42 | Gray, 43 | Cyan, 44 | None 45 | }; 46 | 47 | #if defined(_WIN32) 48 | // Get the Windows color code for a given ConsoleColor 49 | inline WORD GetColorCode(ConsoleColor color) 50 | { 51 | switch (color) { 52 | case ConsoleColor::Green: 53 | return FOREGROUND_GREEN; 54 | case ConsoleColor::Black: 55 | return 0; 56 | case ConsoleColor::Blue: 57 | return FOREGROUND_BLUE; 58 | case ConsoleColor::Gray: 59 | return FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; 60 | case ConsoleColor::Purple: 61 | return FOREGROUND_BLUE | FOREGROUND_RED; 62 | case ConsoleColor::Red: 63 | return FOREGROUND_RED; 64 | case ConsoleColor::White: 65 | return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN; 66 | case ConsoleColor::Cyan: 67 | return FOREGROUND_BLUE | FOREGROUND_GREEN; 68 | case ConsoleColor::Yellow: 69 | return FOREGROUND_RED | FOREGROUND_GREEN; 70 | case ConsoleColor::None: 71 | return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN; 72 | case ConsoleColor::GreenIntensity: 73 | return FOREGROUND_GREEN | FOREGROUND_INTENSITY; 74 | case ConsoleColor::BlackIntensity: 75 | return 0; 76 | case ConsoleColor::BlueIntensity: 77 | return FOREGROUND_BLUE | FOREGROUND_INTENSITY; 78 | case ConsoleColor::GrayIntensity: 79 | return FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; 80 | case ConsoleColor::PurpleIntensity: 81 | return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY; 82 | case ConsoleColor::RedIntensity: 83 | return FOREGROUND_RED | FOREGROUND_INTENSITY; 84 | case ConsoleColor::WhiteIntensity: 85 | return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; 86 | case ConsoleColor::YellowIntensity: 87 | return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; 88 | case ConsoleColor::CyanIntensity: 89 | return FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; 90 | default: 91 | return 0; 92 | } 93 | } 94 | #else 95 | // Get the ANSI escape code for a given ConsoleColor 96 | inline std::string GetColorCode(ConsoleColor color) 97 | { 98 | switch (color) { 99 | case ConsoleColor::Green: 100 | return "\033[32m"; 101 | case ConsoleColor::Black: 102 | return "\033[30m"; 103 | case ConsoleColor::Blue: 104 | return "\033[34m"; 105 | case ConsoleColor::Gray: 106 | return "\033[37m"; 107 | case ConsoleColor::Purple: 108 | return "\033[35m"; 109 | case ConsoleColor::Red: 110 | return "\033[31m"; 111 | case ConsoleColor::White: 112 | return "\033[37m"; 113 | case ConsoleColor::Cyan: 114 | return "\033[36m"; 115 | case ConsoleColor::Yellow: 116 | return "\033[33m"; 117 | case ConsoleColor::None: 118 | return "\033[0m"; 119 | case ConsoleColor::GreenIntensity: 120 | return "\033[32;1m"; 121 | case ConsoleColor::BlackIntensity: 122 | return "\033[30;1m"; 123 | case ConsoleColor::BlueIntensity: 124 | return "\033[34;1m"; 125 | case ConsoleColor::GrayIntensity: 126 | return "\033[37;1m"; 127 | case ConsoleColor::PurpleIntensity: 128 | return "\033[35;1m"; 129 | case ConsoleColor::RedIntensity: 130 | return "\033[31;1m"; 131 | case ConsoleColor::WhiteIntensity: 132 | return "\033[37;1m"; 133 | case ConsoleColor::YellowIntensity: 134 | return "\033[33;1m"; 135 | case ConsoleColor::CyanIntensity: 136 | return "\033[36;1m"; 137 | default: 138 | return 0; 139 | } 140 | } 141 | #endif 142 | 143 | #if defined(_WIN32) 144 | // Get the Windows color code for a given ConsoleBackgroundColor 145 | inline WORD GetBackgroundColorCode(ConsoleBackgroundColor color) 146 | { 147 | switch (color) { 148 | case ConsoleBackgroundColor::Green: 149 | return BACKGROUND_GREEN; 150 | case ConsoleBackgroundColor::Black: 151 | return 0; 152 | case ConsoleBackgroundColor::Blue: 153 | return BACKGROUND_BLUE; 154 | case ConsoleBackgroundColor::Gray: 155 | return 0; 156 | case ConsoleBackgroundColor::Purple: 157 | return BACKGROUND_RED | BACKGROUND_BLUE; 158 | case ConsoleBackgroundColor::Red: 159 | return BACKGROUND_RED; 160 | case ConsoleBackgroundColor::White: 161 | return BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN; 162 | case ConsoleBackgroundColor::Cyan: 163 | return BACKGROUND_BLUE | BACKGROUND_GREEN; 164 | case ConsoleBackgroundColor::Yellow: 165 | return BACKGROUND_RED | BACKGROUND_GREEN; 166 | case ConsoleBackgroundColor::None: 167 | return 0; 168 | default: 169 | return 0; 170 | } 171 | } 172 | #else 173 | // Get the ANSI escape code for a given ConsoleBackgroundColor 174 | inline std::string GetBackgroundColorCode(ConsoleBackgroundColor color) 175 | { 176 | switch (color) { 177 | case ConsoleBackgroundColor::Green: 178 | return "\033[42m"; 179 | case ConsoleBackgroundColor::Black: 180 | return "\033[40m"; 181 | case ConsoleBackgroundColor::Blue: 182 | return "\033[44m"; 183 | case ConsoleBackgroundColor::Gray: 184 | return "\033[40m"; 185 | case ConsoleBackgroundColor::Purple: 186 | return "\033[45m"; 187 | case ConsoleBackgroundColor::Red: 188 | return "\033[41m"; 189 | case ConsoleBackgroundColor::White: 190 | return "\033[47m"; 191 | case ConsoleBackgroundColor::Cyan: 192 | return "\033[46m"; 193 | case ConsoleBackgroundColor::Yellow: 194 | return "\033[43m"; 195 | case ConsoleBackgroundColor::None: 196 | return "\033[40m"; 197 | default: 198 | return 0; 199 | } 200 | } 201 | #endif 202 | 203 | // Operator overloading for console text color 204 | inline std::ostream& operator<<(std::ostream& os, ConsoleColor data) 205 | { 206 | #if defined(_WIN32) 207 | HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); 208 | SetConsoleTextAttribute(handle, GetColorCode(data)); 209 | #else 210 | std::cout << GetColorCode(data); 211 | #endif 212 | return os; 213 | } 214 | 215 | // Operator overloading for console background color 216 | inline std::ostream& operator<<(std::ostream& os, ConsoleBackgroundColor data) 217 | { 218 | #if defined(_WIN32) 219 | HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); 220 | SetConsoleTextAttribute(handle, GetBackgroundColorCode(data)); 221 | #else 222 | std::cout << GetBackgroundColorCode(data); 223 | #endif 224 | return os; 225 | } 226 | -------------------------------------------------------------------------------- /src/csp_base.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CSP_HEADER_H 2 | #define CSP_HEADER_H 3 | 4 | constexpr auto CSP_VERSION = "v1.4.5"; 5 | 6 | #include 7 | 8 | struct CmdParam { 9 | int year{}; 10 | int mon{}; 11 | int day{}; 12 | int hour{}; 13 | int min{}; 14 | int sec{}; 15 | int ju{}; 16 | int type = -1; 17 | int zone = 0; 18 | bool is_auto{false}; 19 | std::string str_dt{}; 20 | int cal_type{1}; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/main.cxx: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Administrator on 2023-10-07. 3 | // 4 | 5 | #include 6 | #include 7 | 8 | #include "CLI11.hpp" 9 | #include "csp_base.hpp" 10 | #include "qmuse.h" 11 | 12 | #ifdef _WIN32 13 | #include 14 | #include 15 | #include 16 | #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING 17 | #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 18 | #endif 19 | #endif 20 | 21 | void recovery_terminal_color() 22 | { 23 | #if defined(_WIN32) 24 | HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE); 25 | if (h_console == NULL) { 26 | fprintf(stderr, "[ERROR] Couldn't handle terminal\n"); 27 | exit(1); 28 | } 29 | if (SetConsoleTextAttribute(h_console, 7) == 0) { 30 | fprintf(stderr, "[ERROR] Couldn't set terminal color\n"); 31 | exit(1); 32 | } 33 | #else 34 | printf("\033[0m"); 35 | #endif 36 | } 37 | 38 | bool parse(const std::string& str, CmdParam& param) 39 | { 40 | std::regex dateRegex(R"((-?\d{1,4})-(\d{1,2})-(\d{1,2})-(\d{1,2})-(\d{1,2})-(\d{1,2}))"); 41 | std::smatch match; 42 | bool is_valid = false; 43 | // 使用正则表达式进行匹配 44 | if (std::regex_search(str, match, dateRegex)) { 45 | param.year = std::stoi(match[1].str()); 46 | param.mon = std::stoi(match[2].str()); 47 | param.day = std::stoi(match[3].str()); 48 | param.hour = std::stoi(match[4].str()); 49 | param.min = std::stoi(match[5].str()); 50 | param.sec = std::stoi(match[6].str()); 51 | } else { 52 | std::cout << "日期字符串格式不正确。" << std::endl; 53 | return false; 54 | } 55 | return true; 56 | } 57 | 58 | bool cmd(int argc, char** argv, CmdParam& param) 59 | { 60 | std::string intro("命令行排盘工具 csp "); 61 | intro.append(CSP_VERSION); 62 | intro.append(" => https://github.com/taynpg/csp"); 63 | CLI::App app(intro); 64 | 65 | app.add_option("-t,--type", param.type, 66 | "==> 盘式类型(必填) <==\n" 67 | "[1,时家转盘超接置润]\n" 68 | "[2,时家转盘阴盘]\n" 69 | "[3,时家转盘拆补]\n" 70 | "[4,时家茅山]"); 71 | 72 | app.add_option("-d,--date", param.str_dt, 73 | "==> 输入日期(默认当前时间) <==\n" 74 | "手动输入格式: 2000-2-3-15-32-11"); 75 | 76 | app.add_option("-c,--calendar", param.cal_type, 77 | "==> 日历类型(默认寿星天文历) <==\n" 78 | "[0,查表法(1901-1-31~2099-12-31)]\n" 79 | "[1,天文历(-198-1-1~9999-12-31)]"); 80 | 81 | app.add_option("-j,--ju", param.ju, "局数(默认自动局数)"); 82 | app.add_option("-z,--zone", param.zone, "与现在的时间差值(单位为小时,默认为0)"); 83 | 84 | try { 85 | CLI11_PARSE(app, argc, argv); 86 | return true; 87 | } catch (const CLI::ParseError& e) { 88 | std::cerr << "Error parsing command line: " << e.what() << std::endl; 89 | return false; 90 | } 91 | return false; 92 | } 93 | 94 | void set_output_supply() 95 | { 96 | #ifdef _WIN32 97 | // 获取标准输出句柄 98 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 99 | // 启用 ANSI 转义代码支持 100 | DWORD mode; 101 | GetConsoleMode(hConsole, &mode); 102 | mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; 103 | SetConsoleMode(hConsole, mode); 104 | #endif 105 | } 106 | 107 | int main(int argc, char** argv) 108 | { 109 | 110 | #if defined(_WIN32) && defined(USE_UTF8_ALL) 111 | system("chcp 65001"); 112 | #endif 113 | 114 | std::shared_ptr deleter(new int(), [](int* p) { 115 | delete p; 116 | recovery_terminal_color(); 117 | }); 118 | 119 | CmdParam param; 120 | set_output_supply(); 121 | 122 | if (!cmd(argc, argv, param)) { 123 | return 0; 124 | } 125 | 126 | if (param.type == -1) { 127 | std::cout << "盘式类型为必填项,-t,可使用--help查看帮助。" << std::endl; 128 | return -1; 129 | } 130 | 131 | if ((param.cal_type != 0) && (param.cal_type != 1)) { 132 | std::cout << "日历类型不正确,可选项[0,1],可使用--help查看帮助。" << std::endl; 133 | return -1; 134 | } 135 | 136 | if (!param.str_dt.empty() && !parse(param.str_dt, param)) { 137 | return -1; 138 | } 139 | switch (param.type) { 140 | case 1: 141 | case 2: 142 | case 3: 143 | case 4: { 144 | CQimenUse qmuse; 145 | if (param.str_dt.empty()) { 146 | param.is_auto = true; 147 | } 148 | qmuse.run(param); 149 | break; 150 | } 151 | default: { 152 | std::wcout << L"未匹配到支持的盘面类型,请使用 --help 查看帮助。"; 153 | } 154 | } 155 | return 0; 156 | } 157 | -------------------------------------------------------------------------------- /src/print.cxx: -------------------------------------------------------------------------------- 1 | #include "print.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "csp_base.hpp" 7 | #include "zh_lang.h" 8 | 9 | constexpr auto SPLIT_LINE = "=============================================="; 10 | 11 | CCmdPrint::CCmdPrint() = default; 12 | 13 | CCmdPrint::~CCmdPrint() = default; 14 | 15 | void CCmdPrint::print_one(int g) 16 | { 17 | const auto& qmd = qm_->get_result(); 18 | if (g == 8) { 19 | std::cout << " "; 20 | return; 21 | } 22 | std::string bashen = CZhData::bs(qmd.bashenr[g]); 23 | std::cout << ConsoleColor::White << " " << bashen << " "; 24 | if (g == qmd.maxing) { 25 | if (g == qmd.kongw[0] || g == qmd.kongw[1]) { 26 | std::cout << ConsoleColor::Cyan << " (" << CZhData::mx() + CZhData::kw() + ")"; 27 | } else { 28 | std::cout << ConsoleColor::Cyan << " (" << CZhData::mx() + ") "; 29 | } 30 | } else if (g == qmd.kongw[0] || g == qmd.kongw[1]) { 31 | std::cout << ConsoleColor::Cyan << " (" << CZhData::kw() + ") "; 32 | } else { 33 | std::cout << " "; 34 | } 35 | } 36 | 37 | void CCmdPrint::print_two(int g) 38 | { 39 | const auto& qmd = qm_->get_result(); 40 | if (g == 8) { 41 | std::cout << " "; 42 | return; 43 | } 44 | std::string jiuxing = CZhData::jx(qmd.jiuxr[g]); 45 | std::cout << ConsoleColor::Green << " " << jiuxing << " "; 46 | bool isJi = false; 47 | std::string szJi; 48 | // 如果此宫的星是寄宫星,那么就寄到这里 49 | if (qmd.jiuxr[g] == qmd.jiuxp[qmd.jigong]) { 50 | isJi = true; 51 | szJi = CZhData::gan(qmd.dp[8]); 52 | } 53 | std::string tian = CZhData::gan(qmd.tp[g]); 54 | std::string szprint = tian; 55 | if (isJi) { 56 | szprint += szJi + " "; 57 | } else { 58 | szprint += " "; 59 | } 60 | std::cout << ConsoleColor::YellowIntensity << szprint; 61 | } 62 | 63 | void CCmdPrint::print_three(int g) 64 | { 65 | const auto& qmd = qm_->get_result(); 66 | if (g == 8) { 67 | std::cout << " "; 68 | return; 69 | } 70 | std::string bamen = CZhData::bm(qmd.bamenr[g]); 71 | std::cout << ConsoleColor::Cyan << " " << bamen << " "; 72 | bool isJi = false; 73 | std::string szJi; 74 | // 如果此宫的星是寄宫星,那么就寄到这里 75 | if (g == qmd.jigong) { 76 | isJi = true; 77 | szJi = CZhData::gan(qmd.dp[8]); 78 | } 79 | std::string di = CZhData::gan(qmd.dp[g]); 80 | std::string szprint = di; 81 | if (isJi) { 82 | szprint += szJi + " "; 83 | } else { 84 | szprint += " "; 85 | } 86 | std::cout << ConsoleColor::Yellow << szprint; 87 | } 88 | 89 | void CCmdPrint::print_base() 90 | { 91 | auto qmd = qm_->get_result(); 92 | auto cal = qm_->get_cal(); 93 | const auto& solar = qm_->get_cal()->get_solar(); 94 | const auto& lunar = qm_->get_cal()->get_lunar(); 95 | 96 | std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 97 | 98 | std::cout << "公元:" << ConsoleColor::Cyan << std::setw(4) << std::setfill('0') << solar.year << "年"; 99 | std::cout << ConsoleColor::Cyan << std::setw(2) << std::setfill('0') << solar.mon << "月"; 100 | std::cout << ConsoleColor::Cyan << std::setw(2) << std::setfill('0') << solar.day << "日 "; 101 | std::cout << ConsoleColor::Cyan << std::setw(2) << std::setfill('0') << solar.hour << "时"; 102 | std::cout << ConsoleColor::Cyan << std::setw(2) << std::setfill('0') << solar.min << "分"; 103 | std::cout << ConsoleColor::Cyan << std::setw(2) << std::setfill('0') << solar.sec << "秒 "; 104 | std::cout << ConsoleColor::Cyan << CSP_VERSION << std::endl; 105 | 106 | std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 107 | 108 | std::string yearStr{}; 109 | int lyear{}; 110 | if (lunar.year < 0) { 111 | lyear = -lunar.year; 112 | yearStr.append("前"); 113 | } else { 114 | lyear = lunar.year; 115 | } 116 | 117 | bool add = false; 118 | int oya = lyear / 1000; 119 | int oyb = lyear / 100 % 10; 120 | int oyc = lyear / 10 % 10; 121 | int oyd = lyear % 10; 122 | 123 | if (oya != 0) 124 | add = true; 125 | if (add) 126 | yearStr.append(CZhData::num(oya)); 127 | if (oyb != 0) 128 | add = true; 129 | if (add) 130 | yearStr.append(CZhData::num(oyb)); 131 | if (oyc != 0) 132 | add = true; 133 | if (add) 134 | yearStr.append(CZhData::num(oyc)); 135 | if (oyd != 0) 136 | add = true; 137 | if (add) 138 | yearStr.append(CZhData::num(oyd)); 139 | 140 | const auto& gz = cal->get_ganzhi(); 141 | std::cout << "阴历:" << ConsoleColor::Cyan << yearStr << "年 "; 142 | std::cout << ConsoleColor::Cyan << CZhData::mon(lunar.mon - 1) << "月"; 143 | std::cout << ConsoleColor::Cyan << CZhData::lunar_day(lunar.day - 1) << "日 "; 144 | std::cout << ConsoleColor::Cyan << CZhData::zhi((lunar.hour + 1) / 2 % 12) << "时\n"; 145 | 146 | // std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 147 | std::cout << "干支:" << ConsoleColor::Yellow << CZhData::gan(gz.yg) << " "; 148 | std::cout << CZhData::gan(gz.mg) << " "; 149 | std::cout << CZhData::gan(gz.dg) << " "; 150 | std::cout << CZhData::gan(gz.hg) << " \n"; 151 | std::cout << " " << CZhData::zhi(gz.yz) << " "; 152 | std::cout << CZhData::zhi(gz.mz) << " "; 153 | std::cout << CZhData::zhi(gz.dz) << " "; 154 | std::cout << CZhData::zhi(gz.hz) << " "; 155 | 156 | switch (type_) { 157 | case 1: { 158 | std::cout << ConsoleColor::Cyan << "<时家转盘超接置润法>" << std::endl; 159 | break; 160 | } 161 | case 2: { 162 | std::string szYueJiang = CZhData::zhi(12 - cal->get_lunar().mon); 163 | std::cout << ConsoleColor::Cyan << " (月将:" << szYueJiang << ")(时家阴盘)" << std::endl; 164 | break; 165 | } 166 | case 3: { 167 | std::cout << ConsoleColor::Cyan << " <时家转盘拆补法>" << std::endl; 168 | break; 169 | } 170 | case 4: { 171 | std::cout << ConsoleColor::Cyan << " <时家转盘茅山法>" << std::endl; 172 | break; 173 | } 174 | default: 175 | break; 176 | } 177 | 178 | std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 179 | 180 | std::cout << "值符:" << ConsoleColor::Yellow << CZhData::jx(qmd.jiuxp[qmd.duty]); 181 | std::cout << " 值使:" << ConsoleColor::Yellow << CZhData::bm(qmd.bamenp[qmd.duty]) << " "; 182 | 183 | std::string szYuan; 184 | switch (qmd.yuan) { 185 | case 0: 186 | szYuan = "手动定局"; 187 | break; 188 | case 1: 189 | szYuan = "下元"; 190 | break; 191 | case 2: 192 | szYuan = "中元"; 193 | break; 194 | case 3: 195 | szYuan = "上元"; 196 | break; 197 | default: 198 | break; 199 | } 200 | std::string jieQi = CZhData::jq(qmd.jieq); 201 | if (qmd.yuan == 0) { 202 | szYuan = " [" + szYuan + "]"; 203 | } else { 204 | szYuan = " [" + jieQi + szYuan + "]"; 205 | } 206 | std::cout << ConsoleColor::Yellow << szYuan; 207 | 208 | std::string dun; 209 | if (qmd.is_yin) { 210 | dun = "[阴遁" + CZhData::num(qmd.ju) + "局]\n"; 211 | } else { 212 | dun = "[阳遁" + CZhData::num(qmd.ju) + "局]\n"; 213 | } 214 | std::cout << ConsoleColor::Yellow << dun; 215 | std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 216 | } 217 | 218 | void CCmdPrint::print_other() 219 | { 220 | auto qmd = qm_->get_result(); 221 | std::cout << "旬空:"; 222 | std::string szXunkong; 223 | szXunkong += CZhData::zhi(qmd.xunkong[0]) + CZhData::zhi(qmd.xunkong[1]) + " "; 224 | szXunkong += CZhData::zhi(qmd.xunkong[2]) + CZhData::zhi(qmd.xunkong[3]) + " "; 225 | szXunkong += CZhData::zhi(qmd.xunkong[4]) + CZhData::zhi(qmd.xunkong[5]) + " "; 226 | szXunkong += CZhData::zhi(qmd.xunkong[6]) + CZhData::zhi(qmd.xunkong[7]) + " \n"; 227 | std::cout << ConsoleColor::Yellow << szXunkong; 228 | std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 229 | 230 | std::string szJieName; 231 | const auto& first_jq = qm_->get_cal()->get_jq_info()[2]; 232 | const auto& second_jq = qm_->get_cal()->get_jq_info()[3]; 233 | szJieName += "[" + CZhData::jq(first_jq.index) + "]:"; 234 | std::cout << szJieName; 235 | char szTem[128]{}; 236 | std::snprintf(szTem, sizeof(szTem), "%02d-%02d %02d:%02d:%02d", first_jq.dt.mon, first_jq.dt.day, first_jq.dt.hour, 237 | first_jq.dt.min, first_jq.dt.sec); 238 | std::cout << ConsoleColor::Yellow << std::string(szTem); 239 | szJieName.clear(); 240 | szJieName += " [" + CZhData::jq(second_jq.index) + "]:"; 241 | std::cout << szJieName; 242 | std::snprintf(szTem, sizeof(szTem), "%02d-%02d %02d:%02d:%02d", second_jq.dt.mon, second_jq.dt.day, second_jq.dt.hour, 243 | second_jq.dt.min, second_jq.dt.sec); 244 | std::cout << ConsoleColor::Yellow << std::string(szTem) << std::endl; 245 | std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 246 | std::cout << ConsoleColor::Yellow << "https://github.com/taynpg/csp" << std::endl; 247 | std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 248 | } 249 | 250 | void CCmdPrint::run(const std::shared_ptr& qm, int type) 251 | { 252 | type_ = type; 253 | this->qm_ = qm; 254 | 255 | print_base(); 256 | std::cout << ConsoleColor::Green << "|"; 257 | print_one(4); 258 | std::cout << ConsoleColor::Green << "|"; 259 | print_one(3); 260 | std::cout << ConsoleColor::Green << "|"; 261 | print_one(2); 262 | std::cout << ConsoleColor::Green << "|\n"; 263 | 264 | std::cout << ConsoleColor::Green << "|"; 265 | print_two(4); 266 | std::cout << ConsoleColor::Green << "|"; 267 | print_two(3); 268 | std::cout << ConsoleColor::Green << "|"; 269 | print_two(2); 270 | std::cout << ConsoleColor::Green << "|\n"; 271 | 272 | std::cout << ConsoleColor::Green << "|"; 273 | print_three(4); 274 | std::cout << ConsoleColor::Green << "|"; 275 | print_three(3); 276 | std::cout << ConsoleColor::Green << "|"; 277 | print_three(2); 278 | std::cout << ConsoleColor::Green << "|\n"; 279 | std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 280 | 281 | std::cout << ConsoleColor::Green << "|"; 282 | print_one(5); 283 | std::cout << ConsoleColor::Green << "|"; 284 | print_one(8); 285 | std::cout << ConsoleColor::Green << "|"; 286 | print_one(1); 287 | std::cout << ConsoleColor::Green << "|\n"; 288 | 289 | std::cout << ConsoleColor::Green << "|"; 290 | print_two(5); 291 | std::cout << ConsoleColor::Green << "|"; 292 | print_two(8); 293 | std::cout << ConsoleColor::Green << "|"; 294 | print_two(1); 295 | std::cout << ConsoleColor::Green << "|\n"; 296 | 297 | std::cout << ConsoleColor::Green << "|"; 298 | print_three(5); 299 | std::cout << ConsoleColor::Green << "|"; 300 | print_three(8); 301 | std::cout << ConsoleColor::Green << "|"; 302 | print_three(1); 303 | std::cout << ConsoleColor::Green << "|\n"; 304 | std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 305 | 306 | std::cout << ConsoleColor::Green << "|"; 307 | print_one(6); 308 | std::cout << ConsoleColor::Green << "|"; 309 | print_one(7); 310 | std::cout << ConsoleColor::Green << "|"; 311 | print_one(0); 312 | std::cout << ConsoleColor::Green << "|\n"; 313 | 314 | std::cout << ConsoleColor::Green << "|"; 315 | print_two(6); 316 | std::cout << ConsoleColor::Green << "|"; 317 | print_two(7); 318 | std::cout << ConsoleColor::Green << "|"; 319 | print_two(0); 320 | std::cout << ConsoleColor::Green << "|\n"; 321 | 322 | std::cout << ConsoleColor::Green << "|"; 323 | print_three(6); 324 | std::cout << ConsoleColor::Green << "|"; 325 | print_three(7); 326 | std::cout << ConsoleColor::Green << "|"; 327 | print_three(0); 328 | std::cout << ConsoleColor::Green << "|\n"; 329 | std::cout << ConsoleColor::Green << SPLIT_LINE << std::endl; 330 | print_other(); 331 | } 332 | -------------------------------------------------------------------------------- /src/print.h: -------------------------------------------------------------------------------- 1 | #ifndef PRINT_BASE_H 2 | #define PRINT_BASE_H 3 | 4 | #include "qimen.h" 5 | #include "ColorConsole.hpp" 6 | 7 | using namespace csp; 8 | 9 | class CCmdPrint 10 | { 11 | public: 12 | CCmdPrint(); 13 | ~CCmdPrint(); 14 | 15 | public: 16 | void run(const std::shared_ptr& qm, int type); 17 | 18 | private: 19 | void print_one(int nGong); 20 | void print_two(int nGong); 21 | void print_three(int nGong); 22 | void print_base(); 23 | void print_other(); 24 | 25 | private: 26 | std::shared_ptr qm_{}; 27 | int type_{}; 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/qmuse.cxx: -------------------------------------------------------------------------------- 1 | #include "qmuse.h" 2 | #include 3 | #include 4 | 5 | using namespace csp; 6 | 7 | bool CQimenUse::run(const CmdParam& param) 8 | { 9 | DateTime dt{}; 10 | if (!param.is_auto) { 11 | dt.year = param.year; 12 | dt.mon = param.mon; 13 | dt.day = param.day; 14 | dt.hour = param.hour; 15 | dt.min = param.min; 16 | dt.sec = param.sec; 17 | } else { 18 | dt = Calendar::now(); 19 | } 20 | 21 | if (param.type < 1 || param.type > 4) { 22 | std::cout << "不支持的盘类型范围,应当在[1,4]。" << std::endl; 23 | return false; 24 | } 25 | if (param.cal_type < 0 || param.cal_type > 1) { 26 | std::cout << "不支持的日历类型范围,应当在[0,1]。" << std::endl; 27 | return false; 28 | } 29 | 30 | auto cal_type = static_cast(param.cal_type); 31 | auto qm_type = static_cast(param.type); 32 | auto qm = Qimen::instance(qm_type); 33 | 34 | if (param.zone != 0) { 35 | auto pt = Calendar::instance(cal_type); 36 | dt = pt->cal_new_date(dt, param.zone * 3600); 37 | } 38 | if (!qm->generate(dt, param.ju, cal_type)) { 39 | std::cout << qm->get_error() << std::endl; 40 | return false; 41 | } 42 | print_.run(qm, param.type); 43 | return true; 44 | } 45 | -------------------------------------------------------------------------------- /src/qmuse.h: -------------------------------------------------------------------------------- 1 | #ifndef QM_USE_H 2 | #define QM_USE_H 3 | 4 | #include "csp_base.hpp" 5 | #include "print.h" 6 | 7 | class CQimenUse 8 | { 9 | public: 10 | CQimenUse() = default; 11 | ~CQimenUse() = default; 12 | 13 | public: 14 | bool run(const CmdParam& param); 15 | 16 | private: 17 | CCmdPrint print_; 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /sxtwl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(sxtwl) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | set(CMAKE_C_STANDARD 11) 6 | 7 | if(NOT DEFINED USE_UTF8_ALL) 8 | if (MSVC) 9 | add_compile_options(/source-charset:utf-8) 10 | endif() 11 | if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_SYSTEM_NAME MATCHES "Windows") 12 | MESSAGE(STATUS "sxtwl Add MinGW Param.") 13 | add_compile_options(-finput-charset=utf-8) 14 | add_compile_options(-fexec-charset=gbk) 15 | endif() 16 | endif() 17 | file(GLOB SRC_FILES "*.cpp" ) 18 | 19 | if(UNIX) 20 | add_compile_options(-fPIC) 21 | elseif(MSVC) 22 | ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) 23 | endif() 24 | 25 | add_library(sxtwl STATIC ${SRC_FILES}) 26 | target_include_directories(sxtwl PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -------------------------------------------------------------------------------- /sxtwl/JD.cpp: -------------------------------------------------------------------------------- 1 | #include "JD.h" 2 | #include "const.h" 3 | #include 4 | #include 5 | 6 | 7 | //https://github.com/guolisen/YiEngine/blob/2ce67dc91fd5fea8e394a5af60dc1e56c5044452/src/DateTime/JulianDay.cpp 8 | //公历转儒略日 9 | double JD::DD2JD(int y, uint8_t m, double d) 10 | { 11 | int n = 0, G = 0; 12 | //判断是否为格里高利历日1582*372+10*31+15 13 | if (y * 372 + m * 31 + (int)(d) >= 588829) 14 | { 15 | G = 1; 16 | } 17 | if (m <= 2) 18 | { 19 | m += 12, y--; 20 | } 21 | //加百年闰 22 | if (G) 23 | { 24 | n = int2(y / 100), n = 2 - n + int(n / 4); 25 | } 26 | 27 | return int2(365.25*(y + 4716)) + int2(30.6001*(m + 1)) + d + n - 1524.5; 28 | 29 | } 30 | 31 | //儒略日数转公历 32 | Time JD::JD2DD(double jd) 33 | { 34 | Time r; 35 | int D = int2(jd + 0.5); 36 | float F = jd + 0.5 - D, c; //取得日数的整数部份A及小数部分F 37 | if (D >= 2299161) 38 | { 39 | c = int((D - 1867216.25) / 36524.25), D += 1 + c - int2(c / 4); 40 | } 41 | D += 1524; r.Y = int2((D - 122.1) / 365.25);//年数 42 | D -= int2(365.25*r.Y); r.M = int2(D / 30.601); //月数 43 | D -= int2(30.601*r.M); r.D = D; //日数 44 | if (r.M > 13) 45 | { 46 | r.M -= 13, r.Y -= 4715; 47 | } 48 | else 49 | { 50 | r.M -= 1, r.Y -= 4716; 51 | } 52 | //日的小数转为时分秒 53 | F *= 24; r.h = int2(F); F -= r.h; 54 | F *= 60; r.m = int2(F); F -= r.m; 55 | F *= 60; r.s = F; 56 | return r; 57 | } 58 | 59 | double JD::toJD(Time& time) 60 | { 61 | return JD::DD2JD(time.Y, time.M, time.D + ((time.s / 60 + time.m) / 60 + time.h) / 24); 62 | } 63 | 64 | //提取jd中的时间(去除日期); 65 | std::string JD::timeStr(double jd) 66 | { 67 | int h, m, s; 68 | jd += 0.5; jd = (jd - int2(jd)); 69 | s = int2(jd * 86400 + 0.5); 70 | h = int2(s / 3600); s -= h * 3600; 71 | m = int2(s / 60); s -= m * 60; 72 | std::string ret = ""; 73 | char buff[11]; 74 | memset(buff, 0, 11); 75 | std::snprintf(buff, sizeof(buff), "0%d", h); 76 | ret.append(buff + strlen(buff) - 2); 77 | ret += ":"; 78 | 79 | memset(buff, 0, 11); 80 | std::snprintf(buff, sizeof(buff), "0%d", m); 81 | ret.append(buff + strlen(buff) - 2); 82 | ret += ":"; 83 | 84 | memset(buff, 0, 11); 85 | std::snprintf(buff, sizeof(buff), "0%d", s); 86 | ret.append(buff + strlen(buff) - 2); 87 | 88 | return ret; 89 | } 90 | -------------------------------------------------------------------------------- /sxtwl/JD.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | struct Time { 8 | int Y, M, D; 9 | double h, m, s; 10 | Time() {}; 11 | Time(const Time& rhs) 12 | { 13 | if (&rhs == this) { 14 | return; 15 | } 16 | this->Y = rhs.Y; 17 | this->M = rhs.M; 18 | this->D = rhs.D; 19 | this->h = rhs.h; 20 | this->m = rhs.m; 21 | this->s = rhs.s; 22 | } 23 | Time(int year, int month, int day, double hour, double min, double sec) 24 | { 25 | this->Y = year; 26 | this->M = month; 27 | this->D = day; 28 | this->h = hour; 29 | this->m = min; 30 | this->s = sec; 31 | } 32 | 33 | int getYear() 34 | { 35 | return Y; 36 | } 37 | 38 | void setYear(int year) 39 | { 40 | Y = year; 41 | } 42 | 43 | void setMonth(int month) 44 | { 45 | M = month; 46 | } 47 | 48 | int getMonth() 49 | { 50 | return M; 51 | } 52 | 53 | int getDay() 54 | { 55 | return D; 56 | } 57 | 58 | void setDay(int day) 59 | { 60 | D = day; 61 | } 62 | 63 | double getHour() 64 | { 65 | return h; 66 | } 67 | 68 | void setHour(double hour) 69 | { 70 | h = hour; 71 | } 72 | 73 | double getMin() 74 | { 75 | return m; 76 | } 77 | 78 | void setMour(double min) 79 | { 80 | m = min; 81 | } 82 | 83 | double getSec() 84 | { 85 | return s; 86 | } 87 | 88 | void setSec(double sec) 89 | { 90 | s = sec; 91 | } 92 | 93 | std::string toStr() 94 | { 95 | std::stringstream ss; 96 | ss << getYear() << "-" << getMonth() << "-" << getDay() << ' ' << getHour() << ":" << getMin() << ":" << (int)getSec(); 97 | return ss.str(); 98 | } 99 | }; 100 | 101 | class JD 102 | { 103 | public: 104 | // 公历转儒略日 105 | static double DD2JD(int y, uint8_t m, double d); 106 | static Time JD2DD(double jd); 107 | 108 | static double toJD(Time& time); 109 | static std::string timeStr(double jd); 110 | }; 111 | -------------------------------------------------------------------------------- /sxtwl/SSQ.cpp: -------------------------------------------------------------------------------- 1 | #include "SSQ.h" 2 | #include 3 | #include "const.h" 4 | #include "eph.h" 5 | 6 | SSQ::SSQ() 7 | { 8 | 9 | std::string suoS = "", qiS = ""; 10 | // 619-01-21开始16598个朔日修正表 d0=1947168 11 | suoS = "EqoFscDcrFpmEsF2DfFideFelFpFfFfFiaipqti1ksttikptikqckstekqttgkqttgkqteksttikptikq2fjstgjqttjkqttgkqt"; 12 | suoS += "ekstfkptikq2tijstgjiFkirFsAeACoFsiDaDiADc1AFbBfgdfikijFifegF1FhaikgFag1E2btaieeibggiffdeigFfqDfaiBkF"; 13 | suoS += "1kEaikhkigeidhhdiegcFfakF1ggkidbiaedksaFffckekidhhdhdikcikiakicjF1deedFhFccgicdekgiFbiaikcfi1kbFibef"; 14 | suoS += "gEgFdcFkFeFkdcfkF1kfkcickEiFkDacFiEfbiaejcFfffkhkdgkaiei1ehigikhdFikfckF1dhhdikcfgjikhfjicjicgiehdik"; 15 | suoS += "cikggcifgiejF1jkieFhegikggcikFegiegkfjebhigikggcikdgkaFkijcfkcikfkcifikiggkaeeigefkcdfcfkhkdgkegieid"; 16 | suoS += "hijcFfakhfgeidieidiegikhfkfckfcjbdehdikggikgkfkicjicjF1dbidikFiggcifgiejkiegkigcdiegfggcikdbgfgefjF1"; 17 | suoS += "kfegikggcikdgFkeeijcfkcikfkekcikdgkabhkFikaffcfkhkdgkegbiaekfkiakicjhfgqdq2fkiakgkfkhfkfcjiekgFebicg"; 18 | suoS += "gbedF1jikejbbbiakgbgkacgiejkijjgigfiakggfggcibFifjefjF1kfekdgjcibFeFkijcfkfhkfkeaieigekgbhkfikidfcje"; 19 | suoS += "aibgekgdkiffiffkiakF1jhbakgdki1dj1ikfkicjicjieeFkgdkicggkighdF1jfgkgfgbdkicggfggkidFkiekgijkeigfiski"; 20 | suoS += "ggfaidheigF1jekijcikickiggkidhhdbgcfkFikikhkigeidieFikggikhkffaffijhidhhakgdkhkijF1kiakF1kfheakgdkif"; 21 | suoS += "iggkigicjiejkieedikgdfcggkigieeiejfgkgkigbgikicggkiaideeijkefjeijikhkiggkiaidheigcikaikffikijgkiahi1"; 22 | suoS += "hhdikgjfifaakekighie1hiaikggikhkffakicjhiahaikggikhkijF1kfejfeFhidikggiffiggkigicjiekgieeigikggiffig"; 23 | suoS += "gkidheigkgfjkeigiegikifiggkidhedeijcfkFikikhkiggkidhh1ehigcikaffkhkiggkidhh1hhigikekfiFkFikcidhh1hit"; 24 | suoS += "cikggikhkfkicjicghiediaikggikhkijbjfejfeFhaikggifikiggkigiejkikgkgieeigikggiffiggkigieeigekijcijikgg"; 25 | suoS += "ifikiggkideedeijkefkfckikhkiggkidhh1ehijcikaffkhkiggkidhh1hhigikhkikFikfckcidhh1hiaikgjikhfjicjicgie"; 26 | suoS += "hdikcikggifikigiejfejkieFhegikggifikiggfghigkfjeijkhigikggifikiggkigieeijcijcikfksikifikiggkidehdeij"; 27 | suoS += "cfdckikhkiggkhghh1ehijikifffffkhsFngErD1pAfBoDd1BlEtFqA2AqoEpDqElAEsEeB2BmADlDkqBtC1FnEpDqnEmFsFsAFn"; 28 | suoS += "llBbFmDsDiCtDmAB2BmtCgpEplCpAEiBiEoFqFtEqsDcCnFtADnFlEgdkEgmEtEsCtDmADqFtAFrAtEcCqAE1BoFqC1F1DrFtBmF"; 29 | suoS += "tAC2ACnFaoCgADcADcCcFfoFtDlAFgmFqBq2bpEoAEmkqnEeCtAE1bAEqgDfFfCrgEcBrACfAAABqAAB1AAClEnFeCtCgAADqDoB"; 30 | suoS += "mtAAACbFiAAADsEtBqAB2FsDqpFqEmFsCeDtFlCeDtoEpClEqAAFrAFoCgFmFsFqEnAEcCqFeCtFtEnAEeFtAAEkFnErAABbFkAD"; 31 | suoS += "nAAeCtFeAfBoAEpFtAABtFqAApDcCGJ"; 32 | 33 | //1645-09-23开始7567个节气修正表 34 | qiS = "FrcFs22AFsckF2tsDtFqEtF1posFdFgiFseFtmelpsEfhkF2anmelpFlF1ikrotcnEqEq2FfqmcDsrFor22FgFrcgDscFs22FgEe"; 35 | qiS += "FtE2sfFs22sCoEsaF2tsD1FpeE2eFsssEciFsFnmelpFcFhkF2tcnEqEpFgkrotcnEqrEtFermcDsrE222FgBmcmr22DaEfnaF22"; 36 | qiS += "2sD1FpeForeF2tssEfiFpEoeFssD1iFstEqFppDgFstcnEqEpFg11FscnEqrAoAF2ClAEsDmDtCtBaDlAFbAEpAAAAAD2FgBiBqo"; 37 | qiS += "BbnBaBoAAAAAAAEgDqAdBqAFrBaBoACdAAf1AACgAAAeBbCamDgEifAE2AABa1C1BgFdiAAACoCeE1ADiEifDaAEqAAFe1AcFbcA"; 38 | qiS += "AAAAF1iFaAAACpACmFmAAAAAAAACrDaAAADG0"; 39 | 40 | 41 | 42 | SB = jieya(suoS); //定朔修正表解压 43 | QB = jieya(qiS); //定气修正表解压 44 | 45 | 46 | //朔直线拟合参数 47 | long double suoKBTmp[] = { 48 | 1457698.231017,29.53067166, // -721-12-17 h=0.00032 古历·春秋 49 | 1546082.512234,29.53085106, // -479-12-11 h=0.00053 古历·战国 50 | 1640640.735300,29.53060000, // -221-10-31 h=0.01010 古历·秦汉 51 | 1642472.151543,29.53085439, // -216-11-04 h=0.00040 古历·秦汉 52 | 53 | 1683430.509300,29.53086148, // -104-12-25 h=0.00313 汉书·律历志(太初历)平气平朔 54 | 1752148.041079,29.53085097, // 85-02-13 h=0.00049 后汉书·律历志(四分历) 55 | 1807665.420323,29.53059851, // 237-02-12 h=0.00033 晋书·律历志(景初历) 56 | 1883618.114100,29.53060000, // 445-01-24 h=0.00030 宋书·律历志(何承天元嘉历) 57 | 1907360.704700,29.53060000, // 510-01-26 h=0.00030 宋书·律历志(祖冲之大明历) 58 | 1936596.224900,29.53060000, // 590-02-10 h=0.01010 随书·律历志(开皇历) 59 | 1939135.675300,29.53060000, // 597-01-24 h=0.00890 随书·律历志(大业历) 60 | 1947168.00// 619-01-21 61 | }; 62 | 63 | suoKB = new std::vector(suoKBTmp, suoKBTmp + sizeof(suoKBTmp) / sizeof(long double)); 64 | 65 | long double qiKBTmp[] = { 66 | 1640650.479938,15.21842500, // -221-11-09 h=0.01709 古历·秦汉 67 | 1642476.703182,15.21874996, // -216-11-09 h=0.01557 古历·秦汉 68 | 69 | 1683430.515601,15.218750011, // -104-12-25 h=0.01560 汉书·律历志(太初历)平气平朔 回归年=365.25000 70 | 1752157.640664,15.218749978, // 85-02-23 h=0.01559 后汉书·律历志(四分历) 回归年=365.25000 71 | 1807675.003759,15.218620279, // 237-02-22 h=0.00010 晋书·律历志(景初历) 回归年=365.24689 72 | 1883627.765182,15.218612292, // 445-02-03 h=0.00026 宋书·律历志(何承天元嘉历) 回归年=365.24670 73 | 1907369.128100,15.218449176, // 510-02-03 h=0.00027 宋书·律历志(祖冲之大明历) 回归年=365.24278 74 | 1936603.140413,15.218425000, // 590-02-17 h=0.00149 随书·律历志(开皇历) 回归年=365.24220 75 | 1939145.524180,15.218466998, // 597-02-03 h=0.00121 随书·律历志(大业历) 回归年=365.24321 76 | 1947180.798300,15.218524844, // 619-02-03 h=0.00052 新唐书·历志(戊寅元历)平气定朔 回归年=365.24460 77 | 1964362.041824,15.218533526, // 666-02-17 h=0.00059 新唐书·历志(麟德历) 回归年=365.24480 78 | 1987372.340971,15.218513908, // 729-02-16 h=0.00096 新唐书·历志(大衍历,至德历) 回归年=365.24433 79 | 1999653.819126,15.218530782, // 762-10-03 h=0.00093 新唐书·历志(五纪历) 回归年=365.24474 80 | 2007445.469786,15.218535181, // 784-02-01 h=0.00059 新唐书·历志(正元历,观象历) 回归年=365.24484 81 | 2021324.917146,15.218526248, // 822-02-01 h=0.00022 新唐书·历志(宣明历) 回归年=365.24463 82 | 2047257.232342,15.218519654, // 893-01-31 h=0.00015 新唐书·历志(崇玄历) 回归年=365.24447 83 | 2070282.898213,15.218425000, // 956-02-16 h=0.00149 旧五代·历志(钦天历) 回归年=365.24220 84 | 2073204.872850,15.218515221, // 964-02-16 h=0.00166 宋史·律历志(应天历) 回归年=365.24437 85 | 2080144.500926,15.218530782, // 983-02-16 h=0.00093 宋史·律历志(乾元历) 回归年=365.24474 86 | 2086703.688963,15.218523776, // 1001-01-31 h=0.00067 宋史·律历志(仪天历,崇天历) 回归年=365.24457 87 | 2110033.182763,15.218425000, // 1064-12-15 h=0.00669 宋史·律历志(明天历) 回归年=365.24220 88 | 2111190.300888,15.218425000, // 1068-02-15 h=0.00149 宋史·律历志(崇天历) 回归年=365.24220 89 | 2113731.271005,15.218515671, // 1075-01-30 h=0.00038 李锐补修(奉元历) 回归年=365.24438 90 | 2120670.840263,15.218425000, // 1094-01-30 h=0.00149 宋史·律历志 回归年=365.24220 91 | 2123973.309063,15.218425000, // 1103-02-14 h=0.00669 李锐补修(占天历) 回归年=365.24220 92 | 2125068.997336,15.218477932, // 1106-02-14 h=0.00056 宋史·律历志(纪元历) 回归年=365.24347 93 | 2136026.312633,15.218472436, // 1136-02-14 h=0.00088 宋史·律历志(统元历,乾道历,淳熙历) 回归年=365.24334 94 | 2156099.495538,15.218425000, // 1191-01-29 h=0.00149 宋史·律历志(会元历) 回归年=365.24220 95 | 2159021.324663,15.218425000, // 1199-01-29 h=0.00149 宋史·律历志(统天历) 回归年=365.24220 96 | 2162308.575254,15.218461742, // 1208-01-30 h=0.00146 宋史·律历志(开禧历) 回归年=365.24308 97 | 2178485.706538,15.218425000, // 1252-05-15 h=0.04606 淳祐历 回归年=365.24220 98 | 2178759.662849,15.218445786, // 1253-02-13 h=0.00231 会天历 回归年=365.24270 99 | 2185334.020800,15.218425000, // 1271-02-13 h=0.00520 宋史·律历志(成天历) 回归年=365.24220 100 | 2187525.481425,15.218425000, // 1277-02-12 h=0.00520 本天历 回归年=365.24220 101 | 2188621.191481,15.218437494, // 1280-02-13 h=0.00015 元史·历志(郭守敬授时历) 回归年=365.24250 102 | 2322147.76// 1645-09-21 103 | }; 104 | 105 | qiKB = new std::vector(qiKBTmp, qiKBTmp + sizeof(qiKBTmp) / sizeof(long double)); 106 | } 107 | 108 | SSQ::~SSQ() 109 | { 110 | delete suoKB; 111 | delete qiKB; 112 | } 113 | 114 | void str_replace(std::string & str, const std::string strsrc, const std::string strdst) 115 | { 116 | std::string::size_type pos = 0;//位置 117 | std::string::size_type srclen = strsrc.size();//要替换的字符串大小 118 | std::string::size_type dstlen = strdst.size();//目标字符串大小 119 | while ((pos = str.find(strsrc, pos)) != std::string::npos) 120 | { 121 | str.replace(pos, srclen, strdst); 122 | pos += dstlen; 123 | } 124 | } 125 | 126 | 127 | std::string SSQ::jieya(std::string s) { //气朔解压缩 128 | std::string o = "0000000000", o2 = o + o; 129 | str_replace(s, "J", "00"); 130 | str_replace(s, "I", "000"); 131 | str_replace(s, "H", "0000"); 132 | str_replace(s, "G", "00000"); 133 | str_replace(s, "t", "02"); 134 | str_replace(s, "s", "002"); 135 | str_replace(s, "r", "0002"); 136 | str_replace(s, "q", "00002"); 137 | str_replace(s, "p", "000002"); 138 | str_replace(s, "o", "0000002"); 139 | str_replace(s, "n", "00000002"); 140 | str_replace(s, "m", "000000002"); 141 | str_replace(s, "l", "0000000002"); 142 | str_replace(s, "k", "01"); 143 | str_replace(s, "j", "0101"); 144 | str_replace(s, "i", "001"); 145 | str_replace(s, "h", "001001"); 146 | str_replace(s, "g", "0001"); 147 | str_replace(s, "f", "00001"); 148 | str_replace(s, "e", "000001"); 149 | str_replace(s, "d", "0000001"); 150 | str_replace(s, "c", "00000001"); 151 | str_replace(s, "b", "000000001"); 152 | str_replace(s, "a", "0000000001"); 153 | str_replace(s, "A", o2 + o2 + o2); 154 | str_replace(s, "B", o2 + o2 + o); 155 | str_replace(s, "C", o2 + o2); 156 | str_replace(s, "D", o2 + o); 157 | str_replace(s, "E", o2); 158 | str_replace(s, "F", o); 159 | return s; 160 | } 161 | 162 | int SSQ::calc(long double jd, QSType qs) 163 | { 164 | jd += 2451545; 165 | int i; 166 | long double D; 167 | std::string n; 168 | std::vector B = *suoKB; 169 | long double pc = 14; 170 | //如果查的是气朔 171 | if (qs == QType) 172 | { 173 | B = *qiKB, pc = 7; 174 | } 175 | 176 | long double f1 = B[0] - pc, f2 = B[B.size() - 1] - pc, f3 = 2436935; 177 | 178 | if (jd < f1 || jd >= f3) 179 | { 180 | //平气朔表中首个之前,使用现代天文算法。1960.1.1以后,使用现代天文算法 (这一部分调用了qi_high和so_high,所以需星历表支持) 181 | if (qs == QType) 182 | { 183 | return floor(qi_high(floor((jd + pc - 2451259) / 365.2422 * 24) * PI / 12) + 0.5); //2451259是1999.3.21,太阳视黄经为0,春分.定气计算 184 | } 185 | else 186 | { 187 | return floor(so_high(floor((jd + pc - 2451551) / 29.5306) * PI * 2) + 0.5); //2451551是2000.1.7的那个朔日,黄经差为0.定朔计算 188 | } 189 | } 190 | 191 | if (jd >= f1 && jd < f2) { //平气或平朔 192 | for (i = 0; i < B.size(); i += 2) if (jd + pc < B[i + 2]) break; 193 | D = B[i] + B[i + 1] * floor((jd + pc - B[i]) / B[i + 1]); 194 | D = floor(D + 0.5); 195 | if (D == 1683460) D++; //如果使用太初历计算-103年1月24日的朔日,结果得到的是23日,这里修正为24日(实历)。修正后仍不影响-103的无中置闰。如果使用秦汉历,得到的是24日,本行D不会被执行。 196 | return D - 2451545; 197 | } 198 | 199 | if (jd >= f2 && jd < f3) { //定气或定朔 200 | if (qs == QType) { 201 | D = floor(qi_low(floor((jd + pc - 2451259) / 365.2422 * 24) * PI / 12) + 0.5); //2451259是1999.3.21,太阳视黄经为0,春分.定气计算 202 | n = QB.substr(floor((jd - f2) / 365.2422 * 24), 1); //找定气修正值 203 | } 204 | else { 205 | D = floor(so_low(floor((jd + pc - 2451551) / 29.5306) * PI * 2) + 0.5); //2451551是2000.1.7的那个朔日,黄经差为0.定朔计算 206 | n = SB.substr(floor((jd - f2) / 29.5306), 1); //找定朔修正值 207 | } 208 | if (n == "1") return D + 1; 209 | if (n == "2") return D - 1; 210 | return D; 211 | } 212 | return 0; 213 | } 214 | 215 | 216 | long double SSQ::qi_high(long double W) 217 | { 218 | long double t = XL::S_aLon_t2(W) * 36525; 219 | t = t - dt_T(t) + 8.0 / 24.0; 220 | long double v = fmod(t + 0.5, 1) * 86400; 221 | if (v < 1200 || v >86400 - 1200) t = XL::S_aLon_t(W) * 36525 - dt_T(t) + 8.0 / 24.0; 222 | return t; 223 | } 224 | 225 | 226 | long double SSQ::so_high(long double W) 227 | { //较高精度朔 228 | long double t = XL::MS_aLon_t2(W) * 36525; 229 | t = t - dt_T(t) + 8.0 / 24.0; 230 | long double v = fmod(t + 0.5, 1) * 86400; 231 | if (v < 1800 || v >86400 - 1800) t = XL::MS_aLon_t(W) * 36525 - dt_T(t) + 8.0 / 24.0; 232 | return t; 233 | } 234 | 235 | long double SSQ::so_low(long double W) { //低精度定朔计算,在2000年至600,误差在2小时以内(仍比古代日历精准很多) 236 | long double v = 7771.37714500204; 237 | long double t = (W + 1.08472) / v, L; 238 | t -= (-0.0000331*t*t 239 | + 0.10976 *cos(0.785 + 8328.6914*t) 240 | + 0.02224 *cos(0.187 + 7214.0629*t) 241 | - 0.03342 *cos(4.669 + 628.3076*t)) / v 242 | + (32 * (t + 1.8)*(t + 1.8) - 20) / 86400 / 36525; 243 | return t * 36525 + 8.0 / 24.0; 244 | } 245 | 246 | long double SSQ::qi_low(long double W) { //最大误差小于30分钟,平均5分 247 | long double t, L, v = 628.3319653318; 248 | t = (W - 4.895062166) / v; //第一次估算,误差2天以内 249 | t -= (53 * t*t + 334116 * cos(4.67 + 628.307585*t) + 2061 * cos(2.678 + 628.3076*t)*t) / v / 10000000; //第二次估算,误差2小时以内 250 | 251 | L = 48950621.66 + 6283319653.318*t + 53 * t*t //平黄经 252 | + 334166 * cos(4.669257 + 628.307585*t) //地球椭圆轨道级数展开 253 | + 3489 * cos(4.6261 + 1256.61517*t) //地球椭圆轨道级数展开 254 | + 2060.6 * cos(2.67823 + 628.307585*t) * t //一次泊松项 255 | - 994 - 834 * sin(2.1824 - 33.75705*t); //光行差与章动修正 256 | 257 | t -= (L / 10000000 - W) / 628.332 + (32 * (t + 1.8)*(t + 1.8) - 20) / 86400 / 36525; 258 | return t * 36525 + 8.0 / 24.0; 259 | } 260 | 261 | 262 | //农历排月序计算,可定出农历,有效范围:两个冬至之间(冬至一 <= d < 冬至二) 263 | void SSQ::calcY(int jd) { 264 | std::vector& A = ZQ; 265 | std::vector& B = HS; //中气表,日月合朔表(整日) 266 | int i, k; 267 | long double W, w; 268 | 269 | //该年的气 270 | 271 | W = int2((jd - 355 + 183) / 365.2422)*365.2422 + 355; //355是2000.12冬至,得到较靠近jd的冬至估计值 272 | if (calc(W, QType) > jd) 273 | { 274 | W -= 365.2422; 275 | } 276 | 277 | //25个节气时刻(北京时间),从冬至开始到下一个冬至以后; 278 | A.clear(); 279 | for (i = 0; i < 25; i++) 280 | { 281 | int t = calc(W + 15.2184*i, QType); 282 | A.push_back(t); 283 | } 284 | 285 | ZQ_pe1 = calc(W - 15.2, QType); ZQ_pe2 = calc(W - 30.4, QType); //补算二气,确保一年中所有月份的“气”全部被计算在内 286 | //今年"首朔"的日月黄经差w 287 | w = calc(A[0], SType); //求较靠近冬至的朔日 288 | if (w > A[0]) 289 | { 290 | w -= 29.53; 291 | } 292 | 293 | //该年所有朔,包含14个月的始末 294 | B.clear(); 295 | for (i = 0; i < 15; i++) 296 | { 297 | B.push_back( calc(w + 29.5306*i, SType) ); 298 | } 299 | 300 | 301 | //月大小 302 | leap = 0; 303 | dx.clear(); 304 | ym.clear(); 305 | for (i = 0; i < 14; i++) { 306 | dx.push_back( HS[i + 1] - HS[i] ); //月大小 307 | ym.push_back(i); //月序初始化 308 | } 309 | 310 | 311 | //-721年至-104年的后九月及月建问题,与朔有关,与气无关 312 | int YY = int2((ZQ[0] + 10 + 180) / 365.2422) + 2000; //确定年份 313 | if (YY >= -721 && YY <= -104) { 314 | int ns[12]; 315 | int yy; 316 | for (i = 0; i < 3; i++) { 317 | yy = YY + i - 1; 318 | //颁行历年首, 闰月名称, 月建 319 | if (yy >= -721) 320 | { 321 | ns[i] = calc(1457698 - J2000 + int2(0.342 + (yy + 721)*12.368422)*29.5306, SType); 322 | //ns[i + 3] = '十三'; 323 | ns[i + 6] = 2; //春秋历,ly为-722.12.17 324 | } 325 | 326 | if (yy >= -479) 327 | { 328 | 329 | ns[i] = calc(1546083 - J2000 + int2(0.500 + (yy + 479)*12.368422)*29.5306, SType); 330 | //ns[i + 3] = '十三'; 331 | ns[i + 6] = 2; //战国历,ly为-480.12.11 332 | } 333 | if (yy >= -220) { 334 | ns[i] = calc(1640641 - J2000 + int2(0.866 + (yy + 220)*12.369000)*29.5306, SType); 335 | // ns[i + 3] = '后九'; 336 | ns[i + 6] = 11; //秦汉历,ly为-221.10.31 337 | } 338 | } 339 | 340 | int nn, f1; 341 | for (i = 0; i < 14; i++) { 342 | for (nn = 2; nn >= 0; nn--) if (HS[i] >= ns[nn]) break; 343 | f1 = int2((HS[i] - ns[nn] + 15) / 29.5306); //该月积数 344 | if (f1 < 12) ym[i] = (f1 + ns[nn + 6]) % 12; else ym[i] = ns[nn + 3]; 345 | } 346 | return; 347 | } 348 | 349 | 350 | //无中气置闰法确定闰月,(气朔结合法,数据源需有冬至开始的的气和朔) 351 | if (B[13] <= A[24]) { //第13月的月末没有超过冬至(不含冬至),说明今年含有13个月 352 | for (i = 1; B[i + 1] > A[2 * i] && i < 13; i++); //在13个月中找第1个没有中气的月份 353 | leap = i; 354 | for (; i < 14; i++) ym[i]--; 355 | } 356 | 357 | //名称转换(月建别名) 358 | for (i = 0; i < 14; i++) { 359 | int Dm = HS[i] + J2000, v2 = ym[i]; //Dm初一的儒略日,v2为月建序号 360 | int mc = v2 % 12; //月建对应的默认月名称:建子十一,建丑十二,建寅为正…… 361 | if (Dm >= 1724360 && Dm <= 1729794) mc = (v2 + 1) % 12; // 8.01.15至 23.12.02 建子为十二,其它顺推 362 | else if (Dm >= 1807724 && Dm <= 1808699) mc = (v2 + 1) % 12; //237.04.12至239.12.13 建子为十二,其它顺推 363 | else if (Dm >= 1999349 && Dm <= 1999467) mc = (v2 + 2) % 12; //761.12.02至762.03.30 建子为正月,其它顺推 364 | else if (Dm >= 1973067 && Dm <= 1977052) { if (v2 % 12 == 0) mc = 2; if (v2 == 2) mc = 2; } //689.12.18至700.11.15 建子为正月,建寅为一月,其它不变 365 | 366 | if (Dm == 1729794 || Dm == 1808699) 367 | { 368 | mc = 12; 369 | // mc = '拾贰'; //239.12.13及23.12.02均为十二月,为避免两个连续十二月,此处改名 370 | } 371 | ym[i] = mc; 372 | } 373 | } 374 | 375 | -------------------------------------------------------------------------------- /sxtwl/SSQ.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | typedef enum 5 | { 6 | QType, //气 7 | SType //朔 8 | } QSType; 9 | 10 | class SSQ 11 | { 12 | public: 13 | SSQ(); 14 | ~SSQ(); 15 | int calc(long double jd, QSType type); 16 | //较高精度气; 17 | long double qi_high(long double); 18 | //较高精度朔 19 | long double so_high(long double); 20 | long double so_low(long double W); 21 | long double qi_low(long double W); 22 | 23 | void calcY(int jd); 24 | 25 | std::string jieya(std::string s); 26 | 27 | std::vector* suoKB; 28 | std::vector* qiKB; 29 | 30 | 31 | std::vector ZQ; 32 | long double ZQ_pe1, ZQ_pe2; 33 | std::vector HS; 34 | std::vector ym; 35 | std::vector dx; 36 | int leap; 37 | std::string SB, QB; 38 | }; 39 | -------------------------------------------------------------------------------- /sxtwl/XL.cpp: -------------------------------------------------------------------------------- 1 | //#include "XL.h" 2 | //#include "const.h" 3 | //#include 4 | // 5 | //long double XL::S_aLon_t(long double W) 6 | //{ 7 | // long double t, v = 628.3319653318; 8 | // t = (W - 1.75347 - PI) / v; v = E_v(t); //v的精度0.03%,详见原文 9 | // t += (W - S_aLon(t, 10)) / v; v = E_v(t); //再算一次v有助于提高精度,不算也可以 10 | // t += (W - S_aLon(t, -1)) / v; 11 | // return t; 12 | //} 13 | // 14 | ////地球速度,t是世纪数,误差小于万分3 15 | //long double XL::E_v(long double t) 16 | //{ 17 | // long double f = 628.307585*t; 18 | // return 628.332 + 21 * sin(1.527 + f) + 0.44 * sin(1.48 + f * 2) 19 | // + 0.129*sin(5.82 + f)*t + 0.00055*sin(4.21 + f)*t*t; 20 | //} 21 | // 22 | ////太阳视黄经 23 | //long double XL::S_aLon(long double t, long double n) { 24 | // return E_Lon(t, n) + nutationLon2(t) + gxc_sunLon(t) + PI; //注意,这里的章动计算很耗时 25 | //}; 26 | // 27 | //long double XL::E_Lon(long double t, long double n) 28 | //{ 29 | // return XL0_calc(0, 0, t, n); 30 | //} 31 | // 32 | //long double XL::XL0_calc(long double xt, int zn, long double t, int n) 33 | //{ 34 | // static long double XL0_xzb[] = { //行星星历修正表 35 | // //经(角秒),纬(角秒), 距(10-6AU) 36 | // -0.08631, +0.00039, -0.00008, //水星 37 | // -0.07447, +0.00006, +0.00017, //金星 38 | // -0.07135, -0.00026, -0.00176, //火星 39 | // -0.20239, +0.00273, -0.00347, //木星 40 | // -0.25486, +0.00276, +0.42926, //土星 41 | // +0.24588, +0.00345, -14.46266, //天王星 42 | // -0.95116, +0.02481, +58.30651 //海王星 43 | // }; 44 | // 45 | // t /= 10; //转为儒略千年数 46 | // int i, j, v = 0, tn = 1, c; 47 | // long double F = XL0[xt], n1, n2, N; 48 | // var n0, pn = zn * 6 + 1, N0 = F[pn + 1] - F[pn]; //N0序列总数 49 | // for (i = 0; i < 6; i++, tn *= t) { 50 | // n1 = F[pn + i], n2 = F[pn + 1 + i], n0 = n2 - n1; 51 | // if (!n0) continue; 52 | // if (n < 0) N = n2; //确定项数 53 | // else { N = int2(3 * n*n0 / N0 + 0.5) + n1; if (i) N += 3; if (N > n2) N = n2; } 54 | // for (j = n1, c = 0; j < N; j += 3) c += F[j] * Math.cos(F[j + 1] + t*F[j + 2]); 55 | // v += c*tn; 56 | // } 57 | // v /= F[0]; 58 | // if (xt == 0) { //地球 59 | // var t2 = t*t, t3 = t2*t; //千年数的各次方 60 | // if (zn == 0) v += (-0.0728 - 2.7702*t - 1.1019*t2 - 0.0996*t3) / rad; 61 | // if (zn == 1) v += (+0.0000 + 0.0004*t + 0.0004*t2 - 0.0026*t3) / rad; 62 | // if (zn == 2) v += (-0.0020 + 0.0044*t + 0.0213*t2 - 0.0250*t3) / 1000000; 63 | // } 64 | // else { //其它行星 65 | // var dv = XL0_xzb[(xt - 1) * 3 + zn]; 66 | // if (zn == 0) v += -3 * t / rad; 67 | // if (zn == 2) v += dv / 1000000; 68 | // else v += dv / rad; 69 | // } 70 | // return v; 71 | //} 72 | // 73 | // 74 | // 75 | // 76 | -------------------------------------------------------------------------------- /sxtwl/XL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class XL 4 | { 5 | public: 6 | //已知太阳视黄经反求时间 7 | static long double S_aLon_t(long double W); 8 | 9 | //地球速度,t是世纪数,误差小于万分3 10 | static long double E_v(long double t); 11 | 12 | //太阳视黄经 13 | static long double S_aLon(long double t, long double n); 14 | 15 | //地球经度计算,返回Date分点黄经,传入世纪数、取项数 16 | static long double E_Lon(long double t, long double n); 17 | 18 | //xt星体,zn坐标号,t儒略世纪数,n计算项数 19 | static long double XL0_calc(long double xt, int zn, long double t, int n); 20 | 21 | 22 | }; -------------------------------------------------------------------------------- /sxtwl/const.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | //PI 5 | #define PI (3.141592653589793) 6 | 7 | //地球赤道半径(千米) 8 | #define cs_rEar (6378.1366) 9 | //平均半径 10 | #define cs_rEarA (0.99834*cs_rEar) 11 | //地球极赤半径比 12 | #define cs_ba (0.99664719) 13 | //地球极赤半径比的平方 14 | #define cs_ba2 (cs_ba*cs_ba) 15 | //天文单位长度(千米) 16 | #define cs_AU (1.49597870691e8) 17 | //sin(太阳视差) 18 | #define cs_sinP (cs_rEar / cs_AU) 19 | //太阳视差 20 | #define cs_PI ( Math.asin(cs_sinP)) 21 | //光速(行米/秒) 22 | #define cs_GS ( 299792.458) 23 | //每天文单位的光行时间(儒略世纪) 24 | #define cs_Agx ( cs_AU / cs_GS / 86400 / 36525) 25 | //#define cs_xxHH ( new Array(116, 584, 780, 399, 378, 370, 367, 367)) //行星会合周期 26 | //#define xxName ( new Array('地球', '水星', '金星', '火星', '木星', '土星', '天王星', '海王星', '冥王星')) 27 | //每弧度的角秒数 28 | #define rad ( 180 * 3600 / PI) 29 | //每弧度的度数 30 | #define radd ( 180 / PI) 31 | #define pi2 ( PI * 2) 32 | #define pi_2 ( PI / 2) 33 | #define J2000 ( 2451545) 34 | // 35 | #define cs_k ( 0.2725076) //月亮与地球的半径比(用于半影计算) 36 | #define cs_k2 ( 0.2722810) //月亮与地球的半径比(用于本影计算) 37 | #define cs_k0 ( 109.1222) //太阳与地球的半径比(对应959.64) 38 | #define cs_sMoon ( cs_k*cs_rEar*1.0000036*rad) //用于月亮视半径计算 39 | #define cs_sMoon2 ( cs_k2*cs_rEar*1.0000036*rad) //用于月亮视半径计算 40 | #define cs_sSun ( 959.64) //用于太阳视半径计算 41 | 42 | //转整型 43 | //#define int2(v) ((v)>=0?(int)(v):((int)(v)-1)) 44 | #define int2(v) ((int)floor(v)) 45 | //求余 46 | #define fmod2(v, n) ((v%n + n) % n) 47 | -------------------------------------------------------------------------------- /sxtwl/day.cpp: -------------------------------------------------------------------------------- 1 | #include "day.h" 2 | #include "eph.h" 3 | #include "JD.h" 4 | 5 | namespace sxtwl 6 | { 7 | GZ getShiGz(uint8_t dayTg, uint8_t hour, bool isZaoWanZiShi = true); 8 | }; 9 | 10 | void Day::checkSSQ() 11 | { 12 | if (!SSQPtr->ZQ.size() || this->d0 < SSQPtr->ZQ[0] || this->d0 >= SSQPtr->ZQ[24]) 13 | { 14 | SSQPtr->calcY(this->d0); 15 | } 16 | } 17 | 18 | /** 19 | * 确定已经计算过阴历信息 20 | */ 21 | void Day::checkLunarData() 22 | { 23 | // 已经计算过了 24 | if (this->Ldn != 0) 25 | { 26 | return; 27 | } 28 | this->checkSSQ(); 29 | 30 | int mk = int2((this->d0 - SSQPtr->HS[0]) / 30); 31 | if (mk < 13 && SSQPtr->HS[mk + 1] <= this->d0) 32 | { 33 | mk++; //农历所在月的序数 34 | } 35 | 36 | //if (this.d0 == SSQPtr->HS[mk]) { //月的信息 37 | this->Lmc = SSQPtr->ym[mk]; //月名称 38 | this->Ldn = SSQPtr->dx[mk]; //月大小 39 | this->Lleap = (SSQPtr->leap != 0 && SSQPtr->leap == mk); //闰状况 40 | //} 41 | 42 | // 阴历所处的日 43 | this->Ldi = this->d0 - SSQPtr->HS[mk]; 44 | } 45 | 46 | void Day::checkSolarData() 47 | { 48 | if (this->m != 0) 49 | { 50 | return; 51 | } 52 | 53 | Time t = JD::JD2DD(this->d0 + J2000); 54 | this->y = t.Y; 55 | this->d = t.D; 56 | this->m = t.M; 57 | } 58 | 59 | /** 60 | * 计算节气数据 61 | */ 62 | void Day::checkJQData() 63 | { 64 | if (this->qk != -2) 65 | { 66 | return; 67 | } 68 | 69 | this->qk = -1; 70 | this->getJieQiJD(); 71 | 72 | //this->checkSSQ(); 73 | 74 | //int qk = int2((this->d0 - SSQPtr->ZQ[0] - 7) / 15.2184); 75 | //////节气的取值范围是0-23 76 | //if (qk < 23 && this->d0 >= SSQPtr->ZQ[qk + 1]) 77 | //{ 78 | // qk++; 79 | //} 80 | 81 | //this->qk = -1; 82 | //if (this->d0 == SSQPtr->ZQ[qk]) 83 | //{ 84 | // this->qk = qk; 85 | //} 86 | } 87 | 88 | Day *Day::after(int day) 89 | { 90 | return new Day(this->d0 + day); 91 | } 92 | 93 | Day *Day::before(int day) 94 | { 95 | return new Day(this->d0 - day); 96 | } 97 | 98 | /** 99 | * 获取阴历日期 100 | */ 101 | int Day::getLunarDay() 102 | { 103 | this->checkLunarData(); 104 | return this->Ldi + 1; 105 | } 106 | 107 | /** 108 | * 获取阴历月 109 | */ 110 | uint8_t Day::getLunarMonth() 111 | { 112 | this->checkLunarData(); 113 | static const int yueIndex[12] = { 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 114 | return yueIndex[this->Lmc]; 115 | } 116 | 117 | int Day::getLunarYear(bool chineseNewYearBoundary) 118 | { 119 | // 以立春为界 120 | if (chineseNewYearBoundary == false) 121 | { 122 | if (this->Lyear == 0) 123 | { 124 | this->checkSSQ(); 125 | long double D = SSQPtr->ZQ[3] + (this->d0 < SSQPtr->ZQ[3] ? -365 : 0) + 365.25 * 16 - 35; //以立春为界定纪年 126 | this->Lyear = int2(D / 365.2422 + 0.5); 127 | } 128 | return this->Lyear + 1984; 129 | } 130 | // 以春节为界 131 | if (this->Lyear0 == 0) 132 | { 133 | this->checkSSQ(); 134 | int D = SSQPtr->HS[2]; //一般第3个月为春节 135 | for (int j = 0; j < 14; j++) 136 | { //找春节 137 | if (SSQPtr->ym[j] != 2 || SSQPtr->leap == j && j) 138 | continue; 139 | D = SSQPtr->HS[j]; 140 | if (this->d0 < D) 141 | { 142 | D -= 365; 143 | break; 144 | } //无需再找下一个正月 145 | } 146 | D = D + 5810; //计算该年春节与1984年平均春节(立春附近)相差天数估计 147 | this->Lyear0 = int2(D / 365.2422 + 0.5); 148 | } 149 | return this->Lyear0 + 1984; 150 | } 151 | 152 | GZ Day::getYearGZ(bool chineseNewYearBoundary) 153 | { 154 | //以春节为界 155 | if (chineseNewYearBoundary) 156 | { 157 | if (this->Lyear3 == NULL) 158 | { 159 | int year = this->getLunarYear(chineseNewYearBoundary) - 1984; 160 | int D = year + 12000; 161 | this->Lyear3 = new GZ(D % 10, D % 12); 162 | } 163 | return *(this->Lyear3); 164 | } 165 | 166 | // 以立春为界 167 | if (this->Lyear2 == NULL) 168 | { 169 | int year = this->getLunarYear(false) - 1984; 170 | int D = year + 12000; 171 | this->Lyear2 = new GZ(D % 10, D % 12); 172 | } 173 | return *(this->Lyear2); 174 | } 175 | 176 | GZ Day::getMonthGZ() 177 | { 178 | if (this->Lmonth2 == NULL) 179 | { 180 | this->checkSSQ(); 181 | int mk = int2((this->d0 - SSQPtr->ZQ[0]) / 30.43685); 182 | //相对大雪的月数计算,mk的取值范围0-12 183 | if (mk < 12 && this->d0 >= SSQPtr->ZQ[2 * mk + 1]) 184 | mk++; 185 | //相对于1998年12月7(大雪)的月数,900000为正数基数 186 | int D = mk + int2((SSQPtr->ZQ[12] + 390) / 365.2422) * 12 + 900000; 187 | this->Lmonth2 = new GZ(D % 10, D % 12); 188 | } 189 | return *(this->Lmonth2); 190 | } 191 | 192 | GZ Day::getDayGZ() 193 | { 194 | if (this->Lday2 == NULL) 195 | { 196 | int D = this->d0 - 6 + 9000000; 197 | this->Lday2 = new GZ(D % 10, D % 12); 198 | } 199 | return *(this->Lday2); 200 | } 201 | 202 | GZ Day::getHourGZ(uint8_t hour, bool isZaoWanZiShi) 203 | { 204 | GZ dayGZ = this->getDayGZ(); 205 | return sxtwl::getShiGz(dayGZ.tg, hour, isZaoWanZiShi); 206 | } 207 | 208 | bool Day::isLunarLeap() 209 | { 210 | this->checkLunarData(); 211 | return this->Lleap; 212 | } 213 | 214 | int Day::getSolarYear() 215 | { 216 | this->checkSolarData(); 217 | return this->y; 218 | } 219 | 220 | uint8_t Day::getSolarMonth() 221 | { 222 | this->checkSolarData(); 223 | return this->m; 224 | } 225 | 226 | int Day::getSolarDay() 227 | { 228 | this->checkSolarData(); 229 | return this->d; 230 | } 231 | 232 | uint8_t Day::getWeek() 233 | { 234 | if (this->week == 0xFF) 235 | { 236 | this->week = (this->d0 + J2000 + 1 + 7000000) % 7; 237 | } 238 | return this->week; 239 | } 240 | 241 | // 处于该月的第几周 242 | uint8_t Day::getWeekIndex() 243 | { 244 | int i = (this->getSolarDay() - 1) % 7; 245 | 246 | int w0 = 0; 247 | if (this->getWeek() >= i) 248 | { 249 | w0 = this->getWeek() - i; 250 | } 251 | else 252 | { 253 | w0 = this->getWeek() + 7 - i; 254 | } 255 | return int2((w0 + this->getSolarDay() - 1) / 7) + 1; 256 | } 257 | //是否有节气 258 | bool Day::hasJieQi() 259 | { 260 | this->checkJQData(); 261 | return this->qk != -1; 262 | } 263 | // 获取节气 264 | uint8_t Day::getJieQi() 265 | { 266 | this->checkJQData(); 267 | return this->qk; 268 | } 269 | 270 | 271 | 272 | double Day::getJieQiJD() 273 | { 274 | if (this->jqjd != 0) 275 | { 276 | return this->jqjd; 277 | } 278 | 279 | long double d, xn, jd2 = this->d0 + dt_T(this->d0) - (long double)8 / (long double)24; 280 | long double w = XL::S_aLon(jd2 / 36525, 3); 281 | w = int2((w - 0.13) / pi2 * 24) * pi2 / 24; 282 | int D = 0; 283 | 284 | do 285 | { 286 | d = qi_accurate(w); 287 | D = int2(d + 0.5); 288 | // 计算出的节令值 289 | xn = int2(w / pi2 * 24 + 24000006.01) % 24; 290 | w += pi2 / 24; 291 | if (D > this->d0) 292 | break; 293 | if (D < this->d0) 294 | continue; 295 | if (D == this->d0) 296 | { 297 | Time t1 = JD::JD2DD(d); 298 | Time t2 = JD::JD2DD(D + J2000); 299 | 300 | t2.h = t1.h; 301 | t2.m = t1.m; 302 | t2.s = t1.s; 303 | 304 | auto jd = JD::toJD(t2); 305 | 306 | this->jqjd = jd; 307 | this->qk = xn; 308 | break; 309 | } 310 | } while (D + 12 < this->d0); 311 | 312 | return this->jqjd; //+ J2000; 313 | } 314 | 315 | // 获取星座 316 | uint8_t Day::getConstellation() 317 | { 318 | if (this->XiZ == 0xFF) 319 | { 320 | this->checkSSQ(); 321 | int mk = int2((this->d0 - SSQPtr->ZQ[0] - 15) / 30.43685); 322 | //星座所在月的序数,(如果j=13,ob.d0不会超过第14号中气) 323 | if (mk < 11 && this->d0 >= SSQPtr->ZQ[2 * mk + 2]) 324 | { 325 | mk++; 326 | } 327 | this->XiZ = (mk + 12) % 12; 328 | } 329 | return this->XiZ; 330 | } 331 | -------------------------------------------------------------------------------- /sxtwl/day.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "JD.h" 6 | #include "const.h" 7 | #include "SSQ.h" 8 | 9 | static std::unique_ptr SSQPtr(new SSQ()); 10 | 11 | struct GZ 12 | { 13 | GZ(){}; 14 | GZ(uint8_t tg, uint8_t dz) : tg(tg), dz(dz) 15 | { 16 | } 17 | uint8_t tg; 18 | uint8_t dz; 19 | }; 20 | 21 | class Day 22 | { 23 | private: 24 | int d0; //儒略日 25 | 26 | int y; //公历年 27 | uint8_t m; //公历月 28 | int d; 29 | 30 | int Lmc; //阴历月的月 31 | uint8_t Ldi; //阴历月的日 32 | int Ldn; //该阴历月的总天数 33 | bool Lleap; //是不是阴历的润月 34 | 35 | int Lyear; //以立春为界, 定农历纪年(10进制,1984年起算) 36 | int Lyear0; //以正月初一为界,农历纪年(10进制,1984年起算) 37 | 38 | uint8_t week; //星期几 39 | int8_t qk; //节令值 40 | uint8_t XiZ; //星座 41 | double jqjd; //节气最体的时间 42 | 43 | GZ *Lyear2; //干支纪年(立春) 44 | GZ *Lyear3; //干支纪年(正月 春节) 45 | GZ *Lmonth2; //月天干地支 46 | GZ *Lday2; // 日天干地支 47 | 48 | private: 49 | Day(int d0) 50 | { 51 | this->d0 = d0; 52 | this->Ldn = 0; 53 | this->m = 0; 54 | this->qk = -2; 55 | this->Lyear = 0; 56 | this->Lyear0 = 0; 57 | 58 | this->Lyear2 = NULL; 59 | this->Lyear3 = NULL; 60 | this->Lmonth2 = NULL; 61 | this->Lday2 = NULL; 62 | 63 | this->week = 0xFF; 64 | this->XiZ = 0xFF; 65 | this->jqjd = 0; 66 | }; 67 | 68 | void checkSSQ(); 69 | void checkLunarData(); 70 | void checkSolarData(); 71 | void checkJQData(); 72 | 73 | public: 74 | virtual ~Day() 75 | { 76 | if (this->Lyear2) 77 | { 78 | delete this->Lyear2; 79 | this->Lyear2 = NULL; 80 | } 81 | 82 | if (this->Lyear3) 83 | { 84 | delete this->Lyear3; 85 | this->Lyear3 = NULL; 86 | } 87 | 88 | if (this->Lmonth2) 89 | { 90 | delete this->Lmonth2; 91 | this->Lmonth2 = NULL; 92 | } 93 | 94 | if (this->Lday2) 95 | { 96 | delete this->Lday2; 97 | this->Lday2 = NULL; 98 | } 99 | } 100 | 101 | Day *after(int day); 102 | Day *before(int day); 103 | // 获取阴历日期 104 | int getLunarDay(); 105 | //获取阴历月 106 | uint8_t getLunarMonth(); 107 | //获取阴历年 chineseNewYearBoundary是否以春节为界 108 | int getLunarYear(bool chineseNewYearBoundary = true); 109 | //获取阴历年干支 chineseNewYearBoundary是否以春节为界 110 | GZ getYearGZ(bool chineseNewYearBoundary = false); 111 | GZ getMonthGZ(); 112 | GZ getDayGZ(); 113 | // 注意非早晚子时的时候,day要算第二天 114 | GZ getHourGZ(uint8_t hour, bool isZaoWanZiShi = true); 115 | bool isLunarLeap(); 116 | 117 | int getSolarYear(); 118 | uint8_t getSolarMonth(); 119 | int getSolarDay() ; 120 | uint8_t getWeek(); 121 | // 处于该月的第几周 122 | uint8_t getWeekIndex(); 123 | //是否有节气 124 | bool hasJieQi(); 125 | // 获取节气 126 | uint8_t getJieQi() ; 127 | double getJieQiJD(); 128 | // 获取星座 129 | uint8_t getConstellation(); 130 | public: 131 | static Day *fromSolar(int _year, uint8_t _month, int _day) 132 | { 133 | std::shared_ptr