kowala's home

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

2012-09-21

釣魚台是中國人的,支持收復釣魚台,趕走日本人。。。

支持收復釣魚台,趕走日本人。。。
歷史教訓猶在眼前,南京大屠殺國仇家恨。
地不分東南西北,人不分男女老少,聯手抗日。
日本必須付出代價!

阿~ 好像太激動了!這樣會被扣上 "忿青" 帽子。。。

"忿青" > "糞青" 一字之隔而已。。。

算了,我就是不喜歡日本!


看不見的戰爭 - 值得一看
http://www.tudou.com/programs/view/07aItsudrAQ/

RedDragonCastle's channel - 釣魚台新聞頻道
釣魚台相關新聞

2012-10-08 美國會報告:美從未承認日本擁有釣魚台主權

這新聞如屬實,或許可以避免一場戰爭。

2012-09-26 谴责日本"购岛"破坏战后秩序 领导人展现钓鱼岛新思路



2012-09-25 保釣挺進釣魚台3浬 台日水柱對峙


马英九:最近发现清朝古籍有记载钓鱼岛情况 (SD)



2012-09-22 台湾拖救船从钓鱼岛返航 说明出海保钓理由
馬英九硬起來。。。



 海峡两岸2012-09-20 日本首相承认错估中方反应



海峡两岸2012-09-20 日媒:日本自卫队战舰向钓鱼岛移动


正点新闻2012-09-20 石原慎太郎再放厥词警告要"砍"中国海监船


美国否认在钓鱼岛问题上为日本"撑腰"


 

鄰國動向

 凤凰早班车 2012-09-26 美澳韩日联合军演风波不断 韩国拒日舰入港

video


军事报道2012-09-20 俄罗斯"高加索 — 2012"战略军演举行



菲律宾对华外交起内讧 "口水仗"打出惊人内幕


印度试射"烈火4"型弹道导弹 

想知道艦艇如何防禦與追蹤--以色列拉斐爾武器發展局開發的艦載紅外搜索與跟踪系統
 RAFAEL's Sea Spotter System


2012-09-20

農曆程式概念探討(5)

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

前一篇 討論了編表規則,本篇就說明如何把日期資料取出來,原作對農曆主演算法是採用查表,計算過程是先設定一基準日做為第一天,然後計算某日距離基準日之累積日數,再對干支定位。這樣農曆基本日期就完成了,再來是潤飾部分,節氣、生肖、節慶、初十廿卅等等,最後定週休顏色等,這個已經是到了 HTML 語法,屬於介面顯示部分了。

先來看看從表格取出資料的函數

1.取出某年的總日數 lYearDays(y)

function lYearDays(y) {
   var i, sum = 348;
   for(i=0x8000; i>0x8; i>>=1)
      sum += (lunarInfo[y-1900] & i)? 1: 0;  
   return(sum+leapDays(y));
}


先把一年日數以小月29日放進去,再比對大月有幾個,加回去,最後是檢查有無潤月,潤大還是閏小,再加進去。

sum = 348 = 12*29


編表規則中,我們知道最右邊四位元是潤月,我們只需要用到 5-16 位元,代表月份,用紅色來表示,
下面的迴圈中,需要說明的是位元移位的概念,我們用二進位來看 i 就很清楚了。

for(i=0x8000; i>0x8; i>>=1)

i = 0x8000 = 1000 0000 0000 0000    i >>= 1 右旋一次
i = 0x4000 = 0100 0000 0000 0000    i >>= 1 右旋一次
i = 0x2000 = 0010 0000 0000 0000    i >>= 1 右旋一次
i = 0x1000 = 0001 0000 0000 0000    i >>= 1 右旋一次
i = 0x0800 = 0000 1000 0000 0000    i >>= 1 右旋一次
i = 0x0400 = 0000 0100 0000 0000    i >>= 1 右旋一次
i = 0x0200 = 0000 0010 0000 0000    i >>= 1 右旋一次
i = 0x0100 = 0000 0001 0000 0000    i >>= 1 右旋一次
i = 0x0080 = 0000 0000 1000 0000    i >>= 1 右旋一次
i = 0x0040 = 0000 0000 0100 0000    i >>= 1 右旋一次
i = 0x0020 = 0000 0000 0010 0000    i >>= 1 右旋一次
i = 0x0010 = 0000 0000 0001 0000    i >>= 1 右旋一次
i = 0x8; 停止

這樣就可以依序取出月份位元,在利用 AND i 把不要的位元消去,AND 運算符號為 &


lunarInfo[y-1900] & i

如果運算後值為1,代表是大月 30 天,就把 sum +1 否則 + 0

以1901年為例 lunarInfo[1] = 0x04ae0,代表月份的位元為

0x4ae = 0100 1010 1110
月份   = 1234 5678 9abc

若要取出 5 月,則 i = 0x0800 = 0000 1000 0000

    0100 1010 1110
& 0000 1000 0000
=          1

sum +1

最後是檢查該年有無潤月,若有則加潤月天數,使用函式 leapDays(y) 來求算。


2.檢查該年有無潤月

function leapMonth(y) {
   return(lunarInfo[y-1900] & 0xf)
}

這是直接取最右邊4個位元來比對,0表示無潤月,其他數值代表潤幾月。

lunarInfo[y-1900] = 0x04ae0


0x04ae0 = 0000 0100 1010 1110 0000
&       0xf = 0000 0000 0000 0000 1111
=                                                          0

3.傳回潤月天數

function leapDays(y) {
   if(leapMonth(y))  return((lunarInfo[y-1900] & 0x10000)? 30: 29)
   else return(0)
}

假設1  lunarInfo[y-1900] = 0x14b63
有潤月 leapMonth(y) =3

    0x14b63 = 0001 0100 1011 0110 0011
& 0x10000 = 0001 0000 0000 0000 0000
=                          1 結果會傳回 30

假設2  lunarInfo[y-1900] = 0x0b557
有潤月 leapMonth(y) =7

    0x0b557 = 0000 1011 0101 0101 0111
& 0x10000 = 0001 0000 0000 0000 0000
=                          0 結果會傳回 29

條件式 (bool)?true:false;
這等於

if (bool)
  true;
else
  false;

農曆主演算法

上述說明了如何查表取出相應的數值,接著說明如何求出某一日轉農曆日期的物件 Lunar(objDate)。

function Lunar(objDate){...}

objDate 是待查的日期物件,資料型態為 Date() 物件,我們可以賦予它一個值。

例如:2012-10-09

objDate = new Date(2012,9,9); //月份是從 0-11, 日是 1-31

這樣我們就指定了某一天給 objDate 物件了。

而在轉農曆日期的物件 Lunar() 中,使用一些屬性,隨後會透過計算而把值填進去下列屬性。

this.year    //陰曆年(陽曆年)[1]
this.month    //陰曆月(陽曆月)[1]
this.day    //陰曆日(陽曆日)[1]

this.yearCyl    //陰曆年
this.monCyl    //陰曆月
this.dayCyl    //陰曆日

this.isLeap    //潤年

該物件沒有方法,只是負責把指定了某一天轉成相應數值,填入上列屬性中。


轉換過程說明

Lunar() 物件被建立

1. 取基準日 1900-1-31 (此為庚子年農曆正月初一)

2. 將指定日減去基準日再轉豪秒為天數,存放於變數 offset,此為某日距離基準日的日數。

一日 = 24*60*60*1000 = 86400000 ms

offset = (objDate - baseDate) / 86400000;

3. 將此日數 offset 做干支定位

由於基準日是甲辰日,在干支表是排在第 41,所以 offset 必須 +40,這樣就正確定位了。

4. 將月數做干支定位

我們先將 offset 對基準月做一校正,基準月是丁丑月,在干支表是排在第 14,所以先把它 +14 完成初步定位。

干支表

甲子     乙丑     丙寅     丁卯     戊辰     己巳     庚午     辛未     壬申     癸酉
甲戌     乙亥     丙子     丁丑     戊寅     己卯     庚辰     辛巳     壬午     癸未
甲申     乙酉     丙戌     丁亥     戊子     己丑     庚寅     辛卯     壬辰     癸巳
甲午     乙未     丙申     丁酉     戊戌     己亥     庚子     辛丑     壬寅     癸卯
甲辰     乙巳     丙午     丁未     戊申     己酉     庚戌     辛亥     壬子     癸丑
甲寅     乙卯     丙辰     丁巳     戊午     己未     庚申     辛酉     壬戌     癸亥

月數計算比較複雜些,因為陰曆大小月份並不固定,必須查表逐一計算,從基準日到指定日經過了幾個月,再取出對應的干支,潤月則重複該月干支一次。

一開始先由某年總日數開始倒扣 offset,直到 offset 為負值,代表最後一年,不足一年,扣過頭須加回。
接著計算該年某月總日數,開始倒扣 offset,直到 offset 為負值,代表最後一月,不足一月,扣過頭須加回。
在計算某月時,還須考慮潤月,潤月須扣除 offset日數,但不可以累計月數,因為潤月重複該月干支一次。
最後剩下的offset就是日數了,如此完成了陰曆轉換。

這段說明請參考程式碼觀看,便知道我在說甚麼了。

//算出農曆, 傳入日期物件
function Lunar(objDate){  
   var i, leap=0, temp=0;  
   var baseDate = new Date(1900,0,31);//基準日 = 農曆第一天  
   var offset = (objDate - baseDate)/86400000; //一天 = 24*60*60*1000=86400000ms
  
   this.dayCyl = offset + 40;//日干支定位
   this.monCyl = 14;//月干支定位

   //--------------------------------------
   for(i=1900; i<2060 && offset>0; i++) {
      temp = lYearDays(i);//取i年的總天數
      offset -= temp;
      this.monCyl += 12;
   }
   //最後一年
   if(offset<0) {
      offset += temp;
      i--;  //西元 i 年
      this.monCyl -= 12;
   }
   this.year = i
   this.yearCyl = i-1864;//甲子年(公元1864年,1924年,1984年)

   //--------------------------------------
   leap = leapMonth(i);//潤哪個月
   this.isLeap = false;
   for(i=1; i<13 && offset>0; i++) {
      //閏月
      if(leap>0 && i==(leap+1) && this.isLeap==false)
         { --i; this.isLeap = true; temp = leapDays(this.year); }
      else
         { temp = monthDays(this.year, i); }
      //閏月已處裡
      if(this.isLeap==true && i==(leap+1)) this.isLeap = false;

      offset -= temp
      if(this.isLeap == false) this.monCyl++;
   }
   //最後一月
   if(offset==0 && leap>0 && i==leap+1)
      if(this.isLeap)
         { this.isLeap = false; }
      else
         { this.isLeap = true; --i; --this.monCyl;}
   if(offset<0){ offset += temp; --i; --this.monCyl; }
   this.month = i;
   this.day = offset + 1;
}

待續...

[1] .依陳先生指出錯誤改正為農曆年月日

2012-09-09

農曆程式概念探討(4)

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

農曆規則與置閏

開始進入農曆主演算法,原作是採用查表法,對于如何排定表,如何取出對應的日期,後面均會做一說明,但開始前,先對農曆規則做一簡要說明。

一個月,就是月亮繞地球一圈,就是月相由新月(朔)循環到新月(朔)所經過的時間(圖一),平均為 29.530588天(29天12小時44分2.8秒)[1],月球繞地球轉動,又被地球帶著繞日公轉,所以它的軌跡是呈現螺旋前進(圖二),這使得它的計算比地球對日要來得複雜些。

圖一,月相循環


新月(朔)就是月球在地球與太陽一直線上,定義為一個月的開始日。

圖二,月球螺旋前進軌跡模擬計算

十九年置七閏

由月球繞地一周為一個月來推算月球繞日會發現,它的實際月數與陽曆的月數不相符,這必須調整,就好像陽曆 4 年一潤,補一天一樣,但如何去補,這就是十九年置七閏的由來。

月亮繞地球一圈平均為 29.530588 天,一年通常有 12 朔望月 = 354.367056 日,這與回歸年 365.2421990741 日,少了 10.8751430741 日,取其差最少為19年+7閏月。

19 回歸年 365.2421990741*19 = 6939.6017824079 日
十九年置七閏 = (19*12+7)*29.530588 = 6939.68818 日

兩者的天數幾乎相等,因此每隔 19 個回歸年,陽曆與農曆再次同步。


置閏規則

觀察朔日定為每月初一,並應該與節氣配合,合理分配24節氣,這樣才是能夠實用的曆法,一年有24節氣,然而12 朔望月僅僅只有354.367056 日,與回歸年 365.2421990741 日短少,使得24節氣無法平均分配,如何合理分配,何時補足差的日數,這便是置閏規則。

圖三,月相變化圖
 
通常以立春及雨水定在一月裡,跟著以驚蟄及春分定二月,若是閏年就加多一個閏月,但一年 365 天裡只能出現十二個中氣,所以就把沒有中氣的那個月份作為閏月,例如閏二月、閏三月 … 閏十一月,但不會出現閏十二月和閏一月,因為這時地球位於近日點附近,速度較快掃過角度大,故此十二月和一月必有中氣和節氣出現,其他月份較有機會出現無中氣[2]。


編表規則

由於大小月出現並無一定規則,為了準確及簡化計算,我們必須找尋一個標準來制定對照表,這裡以香港天文台公佈的公曆與農曆日期對照表[3]為例來說明編表規則。


由上表可以得知1901年沒有閏月,從1月到12月的天數依次為:
29、30、29、29、30、29、30、29、30、30、30、29。

令大月為1,小月為0,則可以表示為

0100 1010 1110  (不包含閏月)

以16進位表示則為

0x4ae

我們可以用小算盤來轉16進位碼


再把閏月的月份擺在右邊,無閏月設為0

0x4ae0

再以閏大月為1,閏小月為0,擺在左邊

0x04ae0

這樣就完成了編表,以下再舉幾個範例


1982年的數據是:0x0a974
0000 1010 1010 0111 0100
表示1982年的4月為閏月,即有第二個4月,且是閏小月。
從1月到13月的天數依次為:
30、29、30、29、29(閏小)、30、29、30、29、29、30、30、30。

2017年的數據是:0x15176
0001 0101 0001 0111 0110
表示2017年的6月為閏月,即有第二個6月,且是閏大月。
從1月到13月的天數依次為:
29、30、29、30、29、29、30(閏大)、29、30、29、30、30、30。

從1900年到2061年的編表如下

var lunarInfo=new Array(
0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,
0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,
0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,
0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,
0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,
0x06ca0,0x0b550,0x15355,0x04da0,0x0a5d0,0x14573,0x052d0,0x0a9a8,0x0e950,0x06aa0,
0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,
0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b5a0,0x195a6,
0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,
0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,
0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,
0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,
0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,
0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,
0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0,
0x14b63);

待續...

參考資料
1.  维基百科干支  http://zh.wikipedia.org/wiki/朔望月
2.  廿四節氣和閏月 http://forum.hkas.org.hk/viewthread.php?tid=4430
3.  公曆與農曆日期對照表  http://www.hko.gov.hk/gts/time/conversionc.htm

圖一,http://www.cwb.gov.tw/V7/knowledge/planning/sun_moon.htm
圖二,http://blog.sciencenet.cn/blog-362400-278987.html
圖三,http://blog.udn.com/chyyang01/5732435

2012-09-02

農曆程式概念探討(3)

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

開始演算法部分,從哪裡開始呢?先從能夠獨立的模塊開始好了。

二十四節氣

原作者基本上是使用查表法,依照陽曆的節氣順序來定義表格,從陽曆1/1開始,首先遇到的節氣不是"立春",而是"小寒",是在1/6日,幾乎每年都固定在這一天,作者分別計算各節氣距離這基準點的分鐘數而製成下表。

var sTermInfo=new Array(
0,21208,42467,63836,85337,107014,128867,150921,173149,195551,218072,240693,263343,285989,308563,331033,353350,375494,397447,419210,440795,462224,483532,504758);

前面的說明可知,地球繞日的軌道是橢圓,所以並非等速前進,可以參考橢圓軌道的計算方法,或是直接查表,這程式開始是西元1900年,我們把它的數據套進Excel中試算,可以得到上表相同的結果,如圖二所示。

圖一、 二十四節氣時刻


圖二、 二十四節氣時刻試算[3]

先計算出從1/1到1/6日"小寒"經過的秒數525837,令它為基準 0,爾後各節氣累計秒數皆須減525837,再來把它轉成分鐘,就完成了上表了。

使用上則是計算某日到陽曆1/6日"小寒"所經過的分鐘數,然後查表就可以判定哪個節氣,或是某個節氣落在哪一日了。

原程式可以求得 y 年的第 n 個節氣的日期

function sTerm(y,n) {
   var offDate = new Date(
       ( 31556925974*(y-1900)*1000 + sTermInfo[n]*60*1000  ) + Date.UTC(1900,0,6,2,5)
   );
   return(offDate.getUTCDate());
}

說明
31556925974 = 365.2421990741*24*60*60 = 一個回歸年秒數
31556925974*(y-1900)*1000 = y 年距離基準年(1900)的毫秒數
sTermInfo[n]*60*1000 = 第 n 個節氣距離"小寒"的毫秒數
Date.UTC(1900,0,6,2,5)  = 基準年
所以
offDate = (y年毫秒數+第n個節氣毫秒數+ 基準年小寒毫秒數)
轉回日期格式
offDate.getUTCDate()

生肖定位

原作者是取陽曆年來對應生肖,其實應該要取陰曆年才對,不過沒關係,我們就假裝不知道,繼續討論下去。
十二生肖就是12年一循環,如下陣列 Animals[12],所以只要除以12取餘數就能定位了,但是 1900 年是鼠年,應該對應餘數 0,但 1900 不是剛好整除 12,所以要調整為整除,就是1900-4=1896,這樣就恰好整除,對應"鼠"年了。

西元 1900-1-31 光緒26 年 - 農曆歲次-庚子年元月初一【鼠】

先宣告一個十二生肖陣列

var Animals=new Array("鼠","牛","虎","兔","龍","蛇","馬","羊","猴","雞","狗","豬");



var sy=1900;
Animals[(sy-4)%12];

這樣就會取到"鼠"了。


干支定位

中國早在商朝時代,就已經開始使用干支記日了[1],那什麼是干支的規則呢,干支就是天干地支,天干有十地支十二,分別列出如下。

天干 = 甲,乙,丙,丁,戊,己,庚,辛,壬,癸
地支 = 子,丑,寅,卯,辰,巳,午,未,申,酉,戌,亥

配對規則就是天干配地支,依序循環。

第一個天干配第一個地支,就是甲子。
第二個天干配第二個地支,就是乙丑。
第三個天干配第三個地支,就是丙寅。
...
到了第十個就是
第十個天干配第十個地支,就是癸酉。

第十一個呢,就變成天干又重頭開始了
第十一個天干配第十一個地支,就是甲戌。
第十二個天干配第十二個地支,就是乙亥。

所以第十三個換地支重頭開始。
第十三個天干配第十三個地支,就是丙子。
如此循環不已,到了下次甲子,剛好60年一循環。

干支60年各年份名稱
甲子     乙丑     丙寅     丁卯     戊辰     己巳     庚午     辛未     壬申     癸酉
甲戌     乙亥     丙子     丁丑     戊寅     己卯     庚辰     辛巳     壬午     癸未
甲申     乙酉     丙戌     丁亥     戊子     己丑     庚寅     辛卯     壬辰     癸巳
甲午     乙未     丙申     丁酉     戊戌     己亥     庚子     辛丑     壬寅     癸卯
甲辰     乙巳     丙午     丁未     戊申     己酉     庚戌     辛亥     壬子     癸丑
甲寅     乙卯     丙辰     丁巳     戊午     己未     庚申     辛酉     壬戌     癸亥

知道60年一甲子後,該是把今年定位到干支表上,概念是這樣的,必須先找個基準點,然後求出距離幾年,再查表取出干支。
以甲子年為基準年來算,我們很容易可以查到  甲子年有 公元1864年,1924年,1984年。
 
方法1.取1864年為基準,那今年2012年,距離就是

 2012-1864=148年 +1(種樹問題要加1,別跟我說沒種過樹 = =)
 149=60+60+29 => 第 29 個序列  => 壬辰

方法2.干支個別取法,因為陣列索引由 0 起算,所以不用+1
           
天干取 148 % 10 =  8 => 壬
地支取 148 % 12 =  4 => 辰

原作程式寫法就是這樣子(程式寫的真好 ^^)

var Gan=new Array("甲","乙","丙","丁","戊","己","庚","辛","壬","癸");
var Zhi=new Array("子","丑","寅","卯","辰","巳","午","未","申","酉","戍","亥");

function cyclical(num) {
   return(Gan[num%10]+Zhi[num%12]);
}


var year=2012;
cyclical(year-1864);

方法3.或是取公倍數定位法
已知 1924 年為甲子年,該年餘數必須調整為 0,
即 (1924-x)%60 = 0,可得 x 最小為 4

var year=2012;
cyclical(year-4);

這樣也可以取得正確的干支。
上述三種方法都可以正確定位,任選一種使用即可。


民國定位

今年西元 2012 等於民國 101年,兩者差為 2012-101=1911年,所以互換的常數就是 1911。

西元 - 1911 = 民國
民國 + 1911= 西元

我們可以寫個轉換式如下

function getMG(year) {
   return('民國 '+(year-1911)+' 年');
}

getMG(2012);  //取得民國年


共和國定位

共和國是大陸地區使用的記年,全名是中華人民共和國,這裡不上歷史課,簡單說明就好,要深入了解的,自己去查,民國全名是中華民國的簡稱,是國父孫中山先生所創立,後經過了國共之戰,民國38年後,分裂為兩個地區,大陸地區由毛澤東領導,以共和國紀年,台灣地區由蔣中正領導沿用中華民國記年。

民國38年大陸地區為共和國元年

民國38年 + 1911 = 1949 = 共和國元年

所以

西元 - 1949 = 共和國
共和國 + 1949= 西元

//西元 to 共和國
function getGB(year) {
   return('共和國 '+(year-1949)+' 年');
}

若要互換

民國 - 38 = 共和國
共和國 + 38 = 民國

//民國 to 共和國
function getB2G(year) {
   return('共和國 '+(year-38)+' 年');
}

//共和國 to 民國
function getG2B(year) {
   return('民國 '+(year+38)+' 年');
}


佛曆年定位

西元1950年,首屆「世界佛教徒友誼會」在錫蘭首都可倫坡舉辦。會中議決:佛陀誕生於西元前623年,成道於西元前588年,去世於西元前543年。1954年,該年會於緬甸仰光舉行,會中再決議佛教國家以「佛曆」紀元,並以釋迦牟尼涅槃年推算,西元1954年為佛曆2497年。[2]

所以佛曆與西元互換的常數就是 2497-1954 = 543

西元 + 543 = 佛曆
佛曆  - 543 = 西元

轉換式如下

function getBD(year) {
   return('佛曆 '+(year+543)+' 年'); 
}

getBD(2012); //取得佛曆年


待續...

參考資料
1.  维基百科干支  http://zh.wikipedia.org/wiki/干支
2.  维基百科佛曆年 http://zh.wikipedia.org/zh-tw/佛曆
3.  1900年二十四節氣表.xls https://docs.google.com/open?id=0B9_qAWWvUIuUSFh1V3lqcnhLdVU