农历的那些事儿(一)

由于项目中日历需要加一个农历的功能,github关于农历也蛮多,但大都是集成在View中,换个日历View成本太高,所以copy其中一个农历转换代码集成在项目中。但是发现数据不准确,竟然两个初一连在一起。。。所以准备仔细研究一下农历和公历时如何转换的。

农历不像公历那么有规律,农历的数据貌似都是天文台的观测结果然后整理发布出来的。google的结果只有南京紫金山天文台香港天文台捣鼓这事儿。

网上流传的农历数据都是

151648_tLwW_2438532.png

像这样的16进制数组,不知道数据的来源是什么,我根据此博客copy出来的数据换算过来总是相差那么一两天,所以我要自己挖掘农历数据源。google、百度都没什么结果,唯一有用的结果就是香港天文台贴出的1901-2100年公农历PDF。

153825_Hyfk_2438532.png

首先先把这200年的pdf下载下来,无赖没有提供打包下载,只能一张张下载。手动点击太慢了吧,此时需要一个类似迅雷的下载软件。

循环地址下载地址

        String url = "http://www.hko.gov.hk/gts/time/calendar/pdf/";
        for (int i = 1901; i < 2101; i++) {
            System.out.println(url + i + ".pdf");
        }

复制到迅雷

152714_bCdw_2438532.png

下载很快结束了。

152820_DYB6_2438532.png

此时需要Adobe Acrobat DC软件,这玩意儿是付费软件,不过可以免费使用30天,此软件功能强大,值得拥有。Acrobat 把200张pdf合并成一个pdf,为毛要合并?因为随后需要把pdf转成excel,我可不想一张张转换。合并:工具--合并文件

153329_R1uT_2438532.png

选择所有pdf文件,合并。然后导出excel就可以,当然也可以导出xml什么。看你怎么方便怎么处理

153541_eGBf_2438532.png

153744_YFQn_2438532.png

此时Excel文件怎么才能变成我们想要的数据比如json,或者类似上面的16进制数据呢?很简单读取excel文件进行转换就行了嘛。对于咋android程序猿来说不是难事儿,纯java代码就跑出来嘛。当然你也可以来点有些挑战性的,直接搞个PC应用程序来读取excel。以前闲着没事儿捣鼓一点JavaFx,于是就开搞。

先拖个界面出来

154757_SosO_2438532.png

输出路径为读取excel后输出我们想要的数据文件。直接开搞代码

文件选择框

        JFileChooser fileChooser = new JFileChooser();
        //设置选择路径模式
        fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        //设置对话框标题
        fileChooser.setDialogTitle("请选择Excel文件");
        //设置过滤器
        fileChooser.setFileFilter(new ExcelFilter());

        if (JFileChooser.APPROVE_OPTION == fileChooser.showOpenDialog(null)) {//用户点击了确定
            String path = fileChooser.getSelectedFile().getAbsolutePath();//取得路径选择
            System.out.println("path:" + path);
            try {
                readCalendarExcel(path);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

获得excel文件对象

FileInputStream fis = new FileInputStream(new File(path));

应该是获取第一张表的意思。。。没深究api的用法,因为这不是重点,能用就行。。。

XSSFWorkbook book = new XSSFWorkbook(fis);
XSSFSheet sheet = book.getSheetAt(0);

然后就是根据表中数据循环读取,此是分析表中数据,由于是pdf转换而来,存在多个表头,每一年有一个人表头。

155542_lfpE_2438532.png

excel提供数数据是从公历1901-01-01到2100-12-31,相对应的农历是1900-11-11到2100-12-01,表头是公历1-31日:左边第一列是公历的月份。单元格对应的就是农历的日期。

读取单元格内容

List<String> rowArray = new ArrayList<>();
while (cellIterator.hasNext()) {
    Cell cell = cellIterator.next();
    switch (cell.getCellType()) {
        case Cell.CELL_TYPE_STRING:
            String cellString = cell.getStringCellValue();
            if (!cellString.isEmpty()) {
                cellString = cellString.replaceAll("\\s*", "");
                rowArray.add(cellString);
            }
            break;
        case Cell.CELL_TYPE_NUMERIC:
            int cellInt = (int) cell.getNumericCellValue();
            rowArray.add(String.valueOf(cellInt));
            break;
        case Cell.CELL_TYPE_BOOLEAN:
            rowArray.add(String.valueOf(cell.getBooleanCellValue()));
            break;
        default:
    }
}

首先把表头读取出来存入List<Strnig>,不要重复读取做个判断,然后循环读取数据

if (!rowArray.isEmpty() && stringSet.isEmpty() && "公曆日期".equals(rowArray.get(0))) {
    stringSet.addAll(rowArray);
}
if (!rowArray.isEmpty() && rowArray.get(0).endsWith("月")) {
    String solarMonth = rowArray.get(0).substring(0, rowArray.get(0).length() - 1);
    boolean first = true;
    for (int i = 2; i < rowArray.size() - 1; i++) {
        String lunarDay = rowArray.get(i);
        int lunarMonth = 0;
        int leapMonth = 0;
        if (lunarDay.endsWith("月")) {
            if (lunarDay.startsWith("閏")) {
                lunarDay = lunarDay.replace("閏", "");
                lunarMonth = 13;
                leapMonth = mMonths.indexOf(lunarDay.substring(0, lunarDay.indexOf("月")));
            } else {
                lunarMonth = mMonths.indexOf(lunarDay.substring(0, lunarDay.indexOf("月")));
            }
            lunarDay = "初一";
        } else {
            if (!calendarSet.isEmpty())
                lunarMonth = calendarSet.get(calendarSet.size() - 1).lunarMonth;
        }
        String s = lunarDay.substring(0, 1);
        String e = lunarDay.substring(1, 2);
        if (calendarSet.isEmpty()) {
            calendarSet.add(new Calendar(1901, Integer.valueOf(solarMonth), Integer.valueOf(stringSet.get(i - 1)),
                    1900, 11, mExtra.indexOf(s) * 10 + mNumbers.indexOf(e), leapMonth));
        } else {
            Calendar calendar = calendarSet.get(calendarSet.size() - 1);
            int lunarYear, solarYear;
            if ("正月".equals(rowArray.get(i))) {
                lunarYear = calendar.lunarYear + 1;
            } else {
                lunarYear = calendar.lunarYear;
            }
            if ("1月".equals(rowArray.get(0)) && calendar.solarMonth == 12 && first) {
                solarYear = calendar.solarYear + 1;
                first = false;
            } else {
                solarYear = calendar.solarYear;
            }
            calendarSet.add(new Calendar(solarYear, Integer.valueOf(solarMonth), Integer.valueOf(stringSet.get(i - 1)),
                    lunarYear, lunarMonth, (mExtra.indexOf(s) == -1) ? 20 :
                    mExtra.indexOf(s) * 10 + (mExtra.indexOf(s) == 3 ? 0 : mNumbers.indexOf(e)), leapMonth));
        }
    }
}

然后再拆分成单独年月,转换成16进制数组。然后写入文件输出,OK,运行看看。

161131_w3Xu_2438532.png

161209_l65b_2438532.png

OK,转换完毕,去看下结果吧。

161257_cjxV_2438532.png

此时只需要验证一下OK了。JavaFxReadExcel 读取excel转换都上传github上,有兴趣请自行下载。农历pdf和excel包括转换后的文件也再项目中

公农历转换,数据正确性验证见下一篇博客,农历的那些事儿(二)

关于作者

转载于:https://my.oschina.net/u/2438532/blog/759596

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的例子,将HTML和CSS代码呈现出来: HTML代码: ```html <!DOCTYPE html> <html> <head> <title>中国传统文化网页</title> <meta charset="UTF-8"> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <header> <h1>中国传统文化</h1> <nav> <ul> <li><a href="#">春节</a></li> <li><a href="#">中秋节</a></li> <li><a href="#">京剧</a></li> <li><a href="#">书法</a></li> </ul> </nav> </header> <main> <section> <h2>春节</h2> <p>春节是中国最重要的传统节日,通常在农历新年的第一天庆祝。这个节日有着丰富的文化内涵和传统习俗,如贴窗花、放爆竹、吃年夜饭等。</p> <img src="springfestival.jpg" alt="春节"> </section> <section> <h2>中秋节</h2> <p>中秋节是中国传统的农历八月十五日,也是一个重要的传统节日。人们通常会在这一天赏月、吃月饼、喝桂花酒等。</p> <img src="midautumnfestival.jpg" alt="中秋节"> </section> <section> <h2>京剧</h2> <p>京剧是中国传统的戏曲艺术形式之一,发源于北京。它以唱、念、做、打为基本表现形式,通常讲述中国古代历史故事和传统神话传说。</p> <img src="jingju.jpg" alt="京剧"> </section> <section> <h2>书法</h2> <p>书法是中国传统的文化艺术,是汉字的艺术表现形式之一。它具有浓厚的文化内涵和独特的艺术魅力,被誉为“东方艺术明珠”。</p> <img src="calligraphy.jpg" alt="书法"> </section> </main> <footer> <p>版权所有 © 2021 中国传统文化网页</p> </footer> </body> </html> ``` CSS代码: ```css body { margin: 0; padding: 0; font-family: Arial, sans-serif; } header { background-color: #f2f2f2; padding: 20px; } h1 { margin: 0; } nav ul { margin: 0; padding: 0; list-style: none; } nav li { display: inline-block; margin-right: 20px; } nav li a { color: #333; text-decoration: none; } nav li a:hover { color: #f00; } main { padding: 20px; } section { margin-bottom: 20px; } h2 { margin: 0; } p { line-height: 1.5; } img { max-width: 100%; height: auto; display: block; margin: 20px auto; } footer { background-color: #333; color: #fff; text-align: center; padding: 20px; } ``` 希望这个例子可以帮助您将HTML和CSS代码呈现出来!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值