kowala's home

kowala's home
這裡是我的學習筆記,陸續增加中。
http://kowala21.blogspot.com

2012-08-28

農曆程式概念探討(2)

kowala's home
http://kowala21.blogspot.com

前一篇簡單介紹了農曆的一些名詞,本篇先把框架清出來。為了方便查看原始碼,我們必須先把它作一些簡化,只留下必須的框架就好,並且把Javascript 分離出來,用一個檔案儲存它。


 HTML原始碼 (calendar_test.htm)
<HTML>
<HEAD>
<TITLE>Test</TITLE>
<META http-equiv=Content-Type content="text/html; charset=UTF-8">
<script language="JavaScript" src="calendar_test.js"></script>
</HEAD>

<BODY onload=initial() >
<HR align=center width=600 color=black>
<CENTER><FORM name=CLD >
<TABLE><TBODY>
<TR><BR>
  <TD align=middle>   

    <FONT  color=#660080 size=2>時鐘: </FONT>
    <FONT id=Clock color=#660080 size=2 align="center"></FONT>

    <DIV style="Z-INDEX: -1; POSITION: absolute; TOP: 55px">
      <FONT id = YMBG style="FONT-SIZE: 100pt; COLOR: #f0f0f0;
       FONT-FAMILY: 'Arial Black'">&nbsp;2012<BR>&nbsp;SEP</FONT>
    </DIV>

    <TABLE border=0><TBODY>     
     <TR>
        <TD bgColor=#3065bc colSpan=7>

          <FONT style="FONT-SIZE: 9pt" color=#ffffff size=2>&nbsp;西曆&nbsp;
          <SELECT style="FONT-SIZE: 9pt" onchange = changeCld() name= SY >
          <SCRIPT language=JavaScript><!--
            for(i=1900;i<2061;i++) document.write('<option>'+i) ;
          //--></SCRIPT>
          </SELECT>&nbsp;年&nbsp;
          <SELECT style="FONT-SIZE: 9pt" onchange = changeCld() name= SM >
          <SCRIPT language=JavaScript><!--
            for(i=1;i<13;i++) document.write('<option>'+i)
          //--></SCRIPT>
          </SELECT>&nbsp;月&nbsp;
          </FONT>

          <FONT id=GZ face=新細明體 color=#ffffff size=2></FONT><BR>
        </TD>
      </TR>
 
      <TR align=middle bgColor=#e8e8e8>
        <TD width=60>日</TD>
        <TD width=60>一</TD>
        <TD width=60>二</TD>
        <TD width=60>三</TD>
        <TD width=60>四</TD>
        <TD width=60>五</TD>
        <TD width=60>六</TD>
      </TR>

      <SCRIPT language=JavaScript><!--
        showCal();
      //--></SCRIPT>
    </TBODY></TABLE>
  </TD>
  <TD vAlign=top align=middle width=60><BR><BR><BR><BR><BR><BR>
<BUTTON style="FONT-SIZE: 9pt" onClick="pushBtm('YU')" type="button">年↑</BUTTON><BR>
<BUTTON style="FONT-SIZE: 9pt" onClick="pushBtm('YD')" type="button">年↓</BUTTON><BR><BR>
<BUTTON style="FONT-SIZE: 9pt" onClick="pushBtm('MU')" type="button">月↑</BUTTON><BR>
<BUTTON style="FONT-SIZE: 9pt" onClick="pushBtm('MD')" type="button">月↓</BUTTON><BR><BR>
<BUTTON style="FONT-SIZE: 9pt" onClick="pushBtm('XD')" type="button">當月</BUTTON><BR>
  </TD>
</TR></TBODY></TABLE>
</FORM></CENTER>
<HR align=center width=600 color=black>
</BODY></HTML>
 Javascript 原始碼 (calendar_test.js)

//---------------------------------------------------
//訊息盒 Debug 用
function MsgBox(str){alert(str);}
//---------------------------------------------------
var today;
//初始化
function initial(){
   myClock();//啟動時鐘 
}

//時鐘,每秒跳一次
function myClock(){
   today = new Date();
   Clock.innerHTML = today.toLocaleString().replace(/(年|月)/g, "-").replace(/日/, "");
   window.setTimeout("myClock()", 1000);
}

//combobox onchange事件
function changeCld(){
   var y,m,g;
   y=CLD.SY.selectedIndex+1900;
   m=CLD.SM.selectedIndex+1;
   MsgBox(y+' 年 '+m+' 月'); 
   if(y>1874 && y<1909){g=y-1874;GZ.innerHTML = '  光緒 ' + g +' 年 '+m+' 月';}
   if(y>1908 && y<1912){g=y-1908;GZ.innerHTML = '  宣統 ' + g +' 年 '+m+' 月';}
   if(y>1911){g=y-1911;GZ.innerHTML = '  民國 ' + g +' 年 '+m+' 月';}
}


//開始秀陽曆日期+顏色
function showCal(){
  //MsgBox('開始秀陽曆日期');  //Debug 用
  var gNum;
  for(i=0;i<6;i++) { //垂直 有6行
    document.write('<tr align=center>');
    for(j=0;j<7;j++) { //水平
      gNum = i*7+j; //數字定位
      //秀陽曆數字
      document.write('<td id="GD'+gNum+'" onMouseOver="mOvr('+gNum+')" onMouseOut="mOut()"><font id="SD'+
      gNum+'" size=5 face="Arial Black" color=green >'+gNum+'</font>');

      //秀陰曆數字+顏色+節慶      document.write('<br><font id="LD'+ gNum +'"size=2 style="font-size:9pt">'+ gNum +'</font></td>');
    }
    document.write('</tr>');
  }
}

//table onMouseOver事件
function mOvr(){    MsgBox('mOvr()');}

//table onMouseOut事件
function mOut(){    MsgBox('mOut()');}

//右邊按鈕群
function pushBtm(v){
   switch(v){
      case 'YU' :
         MsgBox('pushBtm = YU');
         break;
      case 'YD' :
         MsgBox('pushBtm = YD');
         break;
      case 'MU' :
         MsgBox('pushBtm = MU');
         break;
      case 'MD' :
         MsgBox('pushBtm = MD');
         break;
      default :
         MsgBox('pushBtm = '+v);
         break;
   }
}
 使用到的事件列表
 <BODY onload=initial() >
 <SELECT style="FONT-SIZE: 9pt" onchange = changeCld() name= SY >
 <td id="GD0" onmouseover="mOvr(0)" onmouseout="mOut()">
 <BUTTON style="FONT-SIZE: 9pt" onClick="pushBtm('YU')">年↑</BUTTON>
最後是 javascript 事件
 window.setTimeout("myClock()", 1000);

好了,框架大概就這麼多了,用到的這些都是 HTML 及 javascript 語法。

待續...

2012-08-23

農曆程式概念探討(1)


kowala's home
http://kowala21.blogspot.com

El Universo Hoy - Luna llena. México. 10 de noviembre de 2011. [13]

今天來探討的主題是農曆,這也是常用的功能,但似乎是不那麼好懂,還好,網路上可以找到一支近乎"公版"的農曆程式,也不知原作者姓氏,兩岸三地都有人採用,我們就以它為對象來討論,24節氣精確度計算到分鐘(這隻程式原本的計算方式),沒打算要更精確,基準年依照原程式為1900年小寒為起點。

西元1900年1月  6日 → 清德宗光緒25年(歲次己亥)12月6日 小寒 黃經 285 度[1]。
西元1900年1月31日 → 清德宗光緒26年(歲次庚子) 1月1日【鼠】


http://dolphin.cc.ncu.edu.tw/lunar.html
http://38time.artjoey.com/calendar_big.htm
http://www.time.ac.cn/nongli.htm
...

首先,須先有個曆法的概念,曆法的目的都是用來計算時間,基礎都是建立在觀察,若以觀察對象來分,一般可分為陽曆與陰曆,分別是觀察太陽與月亮。

先說太陽,地球自轉一周為一日,繞日一周為一年(回歸年) = 365.2421990741日 = 365天5小時48分46秒[2],約為 365 又 1/4 天。一般取整數 365 算一年,但少了 1/4 天怎麼辦?那就補回來呀,既是 1/4 天,那就 4 年補一天,調整回來,這就是潤年,多一天。(陽曆)

再來就是陰曆,因為用太陽來排日期,一年轉一周,比較粗糙,改成月亮繞地球一周為一個朔望月[3],每月一循環,這就是陰曆了。當然,這規則遠比陽曆來的複雜許多,而且是建立在觀測上,所以都要以天文台發佈的資料為準,並且各地區(緯度)會有不同的觀測結果。

中國是以農立國,為了在農業應用(主要目的),所以要含入四季的變化,古人把一年分割為24個節氣[4],這是以繞太陽公轉(陽曆)的角度為基礎,再把它加入陰曆之中,稱之為農曆,所以會說農曆是陰陽曆。

二十四節氣
節氣以太陽視黃經為準,從春分起算為黃經0度,視黃經每增15度得一氣,依漢代以來通行之名稱及次序,每年得24氣,有中氣及節氣之分,俗名統稱節氣。

春季
    立春 太陽位於黃經315度,2月3-5日交節
    雨水 太陽位於黃經330度,2月18-20日交節
    驚蟄 太陽位於黃經345度,3月5-7日交節
    春分 太陽位於黃經0度,3月20-22日交節
    清明 太陽位於黃經15度,4月4-6日交節
    穀雨 太陽位於黃經30度,4月19-21日交節
夏季
    立夏 太陽位於黃經45度,5月5-7日交節
    小滿 太陽位於黃經60度,5月20-22日交節
    芒種 太陽位於黃經75度,6月5-7日交節
    夏至 太陽位於黃經90度,6月20-22日交節
    小暑 太陽位於黃經105度,7月6-8日交節
    大暑 太陽位於黃經120度,7月22-24日交節
秋季
    立秋 太陽位於黃經135度,8月7-9日交節
    處暑 太陽位於黃經150度,8月22-24日交節
    白露 太陽位於黃經165度,9月7-9日交節
    秋分 太陽位於黃經180度,9月22-24日交節
    寒露 太陽位於黃經195度,10月7-9日交節
    霜降 太陽位於黃經210度,10月23-24日交節
冬季
    立冬 太陽位於黃經225度,11月7-8日交節
    小雪 太陽位於黃經240度,11月21-23日交節
    大雪 太陽位於黃經255度,12月6-8日交節
    冬至 太陽位於黃經270度,12月21-23日交節
    小寒 太陽位於黃經285度,1月5-7日交節
    大寒 太陽位於黃經300度,1月19-21日交節

二十四節氣(圖一)

二十四節氣(圖二)

二十四節氣(圖三)


二十四節氣運行時間
一般若使用平均時間來計算各節氣到達時間,則會產生相當大的誤差,這是因為地球運行軌道是橢圓形,運行的速率並不是等速,所以運行到各節氣(角度)的時間並不相等,計算方法可以參考"用橢圓軌道公式求出24節氣"[5]及"用天文方法計算二十四節氣"[6]等文章,也可以到這裡[7]查詢某年的節氣時間。

 二十四節氣軌道(圖四)

2012年二十四節氣時間


二十四節氣的意義[8]
以下的解釋是適用於中原地區,為古代農務的依據。

立春:春季開始,立是開始的意思,春是蠢動,表示萬物開始有生氣。
雨水:春到人間,降雨開始增多,春雨綿綿。
驚蟄:蟲類冬眠或隱藏起來,伏著不動,叫做蟄。春雷響起,驚醒蟄伏地下冬眠的蟲類,將開始出土活動。
春分:春季過了一半,此時陽光直射赤道上,這一天太陽從正東方昇起,落於正西方,地球上南北半球受光相等,晝夜長短相等,古代曾稱春分與秋分為晝夜分。
清明:天氣逐漸和暖,春暖花開,草木開始萌發茂盛,大地一片氣清景明的現象。
穀雨:雨生百穀的意思,此時農夫剛完成春耕,田裡的秧苗正需大量的雨水滋潤,適時且足夠的雨水才能使穀物成長茁壯。但此時的氣候,卻時晴時雨,時冷時熱,最讓人不易捉摸。
立夏:夏季開始,此時已出現溫暖的氣候,萬物迅速生長。
小滿:滿指穀物籽粒飽滿,稻穀和麥類等夏熟農作物行將結實,等待成熟,但尚未達到飽滿的程度。
芒種:有芒作物開始成熟,結實成穗,此時也是秋季作物播種的適當時節。
夏至:炎熱的夏天真正到來,此時陽光直射北回歸線上,北半球受光最多,是白天最長黑夜最短的一天,中午時太陽的仰角是一年裡最高的,因此日影是一年中最短的,過了夏至日,白天漸漸變短,夜晚慢慢加長。
小暑:暑是炎熱之意,此時天氣開始逐漸炎熱,但是還沒有熱到極點,雖然夏至時北半球受陽光照射時間最長,由於太陽射來的熱力必須先對地面和大氣加溫,才能把熱儲存於大氣中,所以天氣從夏至開始慢慢加熱,經過小暑後,熱度才會逐漸昇高到極點。
大暑:氣候酷熱到達高峰。
立秋:秋季開始,氣溫將由熱轉涼,涼爽舒適的秋天就要來臨。
處暑:處是止的意思,表示夏天的暑氣到此終止,但有時晴天的下午,炎熱不亞於暑夏,可視為夏的迴光返照。
白露:天氣已經轉涼,夜晚時空氣中所含的水汽,接觸到地面上因輻射而迅速冷卻的物體,於是部份凝結為水滴而附於地面的花草樹葉上,這些透明晶瑩的水珠,我們就稱它為白露。
秋分:秋季過了一半,同春分一樣,此時陽光直射赤道上,地球上南北半球受光相等,晝夜長短相等。
寒露:此時已屆深秋,天氣轉冷,早晚所接觸到的霧氣和露水,感覺寒意沁心,而草木行將枯萎。
霜降:天氣漸寒,當地面的物體溫度降至攝氏零度或以下,接觸的水汽直接結霜附於其上。
立冬:冬季開始,冬是終了,作物已收割貯藏,農事完成。
小雪:氣候寒冷,此時節空氣中的水汽在溫度冷至攝氏零度以下時,會凝成結晶狀的固體由空中降下,稱為降雪,不過降雪量不多且不大。
大雪:天氣更寒冷,大雪紛飛,地面積雪。
冬至:嚴冬來臨,此時陽光直射南回歸線上,北半球受光最少,是白天最短黑夜最長的一天,中午時太陽的仰角是一年裡最低的,日影是一年中最長的。
小寒:天氣相當寒冷,雖進入嚴冬但尚未到達最冷的時候。
大寒:天氣酷寒,是一年中最冷的日子。

時刻
我國是以中央氣象局所在地之時刻為準,欲求其它各地之日中天時刻,應加各地經度差之修正。本地標準時欲改為某地之本地平時者,應視本地經度在時區標準經線之東或西之度數,每度加減4分,東加西減[9]。
地球自轉一周為一日,凌晨12:00(子時)為一日之始。


名詞解釋:
這可以跳過,也可以詳查,並不會影響程式寫作。
朔望月[3] = 指月球連續兩次合朔的時間間隔。因為攝動的關係,朔望月的長度大約在29.27至29.83天之間變動著,長期的平均長度是29.530588天(29天12小時44分2.8秒),或大約是29.5天。新月出現那天為初一。
中氣[10],中氣為「二十四節氣」中,每月的第二個節氣。
包括雨水、春分、穀雨、小滿、夏至、大暑、處暑、秋分、霜降、小雪、冬至和大寒。
黃經[11](太陽經度或天球經度)是在黃道座標系統中用來確定天體在天球上位置的一個座標值(另一個值是黃緯),在這個系統中,天球被黃道平面分割為南北兩個半球。
黃道面[12],地球繞日公轉的軌道平面。


二十四節氣(圖一) http://www.xuanyi.com/zhuanjiaku/qizhengyang/2011/0216/4173.html
二十四節氣(圖二) http://www.worldce.com.cn/wenhua_xiang.asp?id=891
二十四節氣(圖三) http://www.hko.gov.hk/gts/time/24solartermsc.htm
二十四節氣軌道(圖四) http://bieyu.com/astp-doc/a07.htm

待續...

參考資料
1. 兩千年中西曆轉換(西元元年2月11日至2100年2月9日) http://sinocal.sinica.edu.tw
2. 维基百科回歸年  http://zh.wikipedia.org/wiki/回歸年
3. 维基百科朔望月 http://zh.wikipedia.org/zh-tw/朔望月
4. 维基百科農曆 http://zh.wikipedia.org/zh-tw/節氣
5. 用橢圓軌道公式求出24節氣 http://bieyu.com/astp-doc/a07.htm
6. 用天文方法計算二十四節氣 http://blog.csdn.net/orbit/article/details/7910220
7. 查詢二十四節氣表 jieqi.911cha.com
8. 24節氣概述 http://www.youngsun.org.tw:8080/calendar/terms.asp
9. 內政部 國民曆說明 http://www.moi.gov.tw/dca/custom100/home.asp
10. 中氣 http://zh.wikipedia.org/zh-tw/中氣
11. 黃經 http://zh.wikipedia.org/wiki/黃經
12. 黃道面 http://zh.wikipedia.org/wiki/黃道
13. El Universo Hoy  https://www.facebook.com/photo.php?fbid=299524833410887&set=a.292863737410330.86885.211717025525002&type=1&theater#