2 Copyright (C) 2011 by Cuong Le <metacuong@gmail.com>
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>
18 var IMGS_RESOURCE_PATH = "/opt/lichvietwidget/qml/lichvietwidget/imgs/";
23 function refresh(day_center_img, day_left_img, day_right_img, month_left_img, month_right_img, year_1_img, year_2_img,year_3_img,year_4_img, txt_detail) {
24 var date = new Date();
26 var lunar = getLunarDate(date.getDate(),date.getMonth()+1,date.getFullYear());
27 var lunarCanChi = getCanChi(lunar);
29 var xmonth = lunar.month;
30 var xyear = lunar.year;
32 txt_detail.text = "Ngày <b>"+lunarCanChi[0]+"</b>, Tháng <b>"+lunarCanChi[1]+"</b><br>Năm <b>"+lunarCanChi[2]+"</b>";
36 day_center_img.visible = true;
37 day_center_img.source = IMGS_RESOURCE_PATH + xday + ".png";
38 day_left_img.visible = false;
39 day_right_img.visible = false;
41 var strxday = xday+'';
42 var firstday = strxday[0];
43 var secondday = strxday[1];
44 day_center_img.visible = false;
45 day_left_img.visible = true;
46 day_left_img.source = IMGS_RESOURCE_PATH + firstday + ".png";
47 day_right_img.visible = true;
48 day_right_img.source = IMGS_RESOURCE_PATH + secondday + ".png";
53 if (xmonth != ismonth){
55 month_left_img.source = IMGS_RESOURCE_PATH +"0.png";
56 month_right_img.source = IMGS_RESOURCE_PATH + xmonth + ".png";
59 var strxmonth = xmonth+'';
60 var firstmonth = strxmonth[0];
61 var secondmonth = strxmonth[1];
62 month_left_img.source = IMGS_RESOURCE_PATH + firstmonth +".png";
63 month_right_img.source = IMGS_RESOURCE_PATH + secondmonth + ".png";
69 var strxyear = xyear+'';
70 year_1_img.source = IMGS_RESOURCE_PATH + strxyear[0] +".png";
71 year_2_img.source = IMGS_RESOURCE_PATH + strxyear[1] + ".png";
72 year_3_img.source = IMGS_RESOURCE_PATH + strxyear[2] +".png";
73 year_4_img.source = IMGS_RESOURCE_PATH + strxyear[3] + ".png";
79 * Copyright 2004 Ho Ngoc Duc [http://come.to/duc]. All Rights Reserved.<p>
80 * Permission to use, copy, modify, and redistribute this software and its
81 * documentation for personal, non-commercial use is hereby granted provided that
82 * this copyright notice appears in all copies.
85 var ABOUT = "\u00C2m l\u1ECBch Vi\u1EC7t Nam - Version 0.8"+"\n\u00A9 2004 H\u1ED3 Ng\u1ECDc \u0110\u1EE9c [http://come.to/duc]";
87 0x30baa3, 0x56ab50, 0x422ba0, 0x2cab61, 0x52a370, 0x3c51e8, 0x60d160, 0x4ae4b0, 0x376926, 0x58daa0,
88 0x445b50, 0x3116d2, 0x562ae0, 0x3ea2e0, 0x28e2d2, 0x4ec950, 0x38d556, 0x5cb520, 0x46b690, 0x325da4,
89 0x5855d0, 0x4225d0, 0x2ca5b3, 0x52a2b0, 0x3da8b7, 0x60a950, 0x4ab4a0, 0x35b2a5, 0x5aad50, 0x4455b0,
90 0x302b74, 0x562570, 0x4052f9, 0x6452b0, 0x4e6950, 0x386d56, 0x5e5aa0, 0x46ab50, 0x3256d4, 0x584ae0,
91 0x42a570, 0x2d4553, 0x50d2a0, 0x3be8a7, 0x60d550, 0x4a5aa0, 0x34ada5, 0x5a95d0, 0x464ae0, 0x2eaab4,
92 0x54a4d0, 0x3ed2b8, 0x64b290, 0x4cb550, 0x385757, 0x5e2da0, 0x4895d0, 0x324d75, 0x5849b0, 0x42a4b0,
93 0x2da4b3, 0x506a90, 0x3aad98, 0x606b50, 0x4c2b60, 0x359365, 0x5a9370, 0x464970, 0x306964, 0x52e4a0,
94 0x3cea6a, 0x62da90, 0x4e5ad0, 0x392ad6, 0x5e2ae0, 0x4892e0, 0x32cad5, 0x56c950, 0x40d4a0, 0x2bd4a3,
95 0x50b690, 0x3a57a7, 0x6055b0, 0x4c25d0, 0x3695b5, 0x5a92b0, 0x44a950, 0x2ed954, 0x54b4a0, 0x3cb550,
96 0x286b52, 0x4e55b0, 0x3a2776, 0x5e2570, 0x4852b0, 0x32aaa5, 0x56e950, 0x406aa0, 0x2abaa3, 0x50ab50
97 ); /* Years 2000-2099 */
100 0x3c4bd8, 0x624ae0, 0x4ca570, 0x3854d5, 0x5cd260, 0x44d950, 0x315554, 0x5656a0, 0x409ad0, 0x2a55d2,
101 0x504ae0, 0x3aa5b6, 0x60a4d0, 0x48d250, 0x33d255, 0x58b540, 0x42d6a0, 0x2cada2, 0x5295b0, 0x3f4977,
102 0x644970, 0x4ca4b0, 0x36b4b5, 0x5c6a50, 0x466d50, 0x312b54, 0x562b60, 0x409570, 0x2c52f2, 0x504970,
103 0x3a6566, 0x5ed4a0, 0x48ea50, 0x336a95, 0x585ad0, 0x442b60, 0x2f86e3, 0x5292e0, 0x3dc8d7, 0x62c950,
104 0x4cd4a0, 0x35d8a6, 0x5ab550, 0x4656a0, 0x31a5b4, 0x5625d0, 0x4092d0, 0x2ad2b2, 0x50a950, 0x38b557,
105 0x5e6ca0, 0x48b550, 0x355355, 0x584da0, 0x42a5b0, 0x2f4573, 0x5452b0, 0x3ca9a8, 0x60e950, 0x4c6aa0,
106 0x36aea6, 0x5aab50, 0x464b60, 0x30aae4, 0x56a570, 0x405260, 0x28f263, 0x4ed940, 0x38db47, 0x5cd6a0,
107 0x4896d0, 0x344dd5, 0x5a4ad0, 0x42a4d0, 0x2cd4b4, 0x52b250, 0x3cd558, 0x60b540, 0x4ab5a0, 0x3755a6,
108 0x5c95b0, 0x4649b0, 0x30a974, 0x56a4b0, 0x40aa50, 0x29aa52, 0x4e6d20, 0x39ad47, 0x5eab60, 0x489370,
109 0x344af5, 0x5a4970, 0x4464b0, 0x2c74a3, 0x50ea50, 0x3d6a58, 0x6256a0, 0x4aaad0, 0x3696d5, 0x5c92e0
110 ); /* Years 1900-1999 */
112 var TK21 = new Array(
113 0x46c960, 0x2ed954, 0x54d4a0, 0x3eda50, 0x2a7552, 0x4e56a0, 0x38a7a7, 0x5ea5d0, 0x4a92b0, 0x32aab5,
114 0x58a950, 0x42b4a0, 0x2cbaa4, 0x50ad50, 0x3c55d9, 0x624ba0, 0x4ca5b0, 0x375176, 0x5c5270, 0x466930,
115 0x307934, 0x546aa0, 0x3ead50, 0x2a5b52, 0x504b60, 0x38a6e6, 0x5ea4e0, 0x48d260, 0x32ea65, 0x56d520,
116 0x40daa0, 0x2d56a3, 0x5256d0, 0x3c4afb, 0x6249d0, 0x4ca4d0, 0x37d0b6, 0x5ab250, 0x44b520, 0x2edd25,
117 0x54b5a0, 0x3e55d0, 0x2a55b2, 0x5049b0, 0x3aa577, 0x5ea4b0, 0x48aa50, 0x33b255, 0x586d20, 0x40ad60,
118 0x2d4b63, 0x525370, 0x3e49e8, 0x60c970, 0x4c54b0, 0x3768a6, 0x5ada50, 0x445aa0, 0x2fa6a4, 0x54aad0,
119 0x4052e0, 0x28d2e3, 0x4ec950, 0x38d557, 0x5ed4a0, 0x46d950, 0x325d55, 0x5856a0, 0x42a6d0, 0x2c55d4,
120 0x5252b0, 0x3ca9b8, 0x62a930, 0x4ab490, 0x34b6a6, 0x5aad50, 0x4655a0, 0x2eab64, 0x54a570, 0x4052b0,
121 0x2ab173, 0x4e6930, 0x386b37, 0x5e6aa0, 0x48ad50, 0x332ad5, 0x582b60, 0x42a570, 0x2e52e4, 0x50d160,
122 0x3ae958, 0x60d520, 0x4ada90, 0x355aa6, 0x5a56d0, 0x462ae0, 0x30a9d4, 0x54a2d0, 0x3ed150, 0x28e952
123 ); /* Years 2000-2099 */
125 var TK22 = new Array(
126 0x4eb520, 0x38d727, 0x5eada0, 0x4a55b0, 0x362db5, 0x5a45b0, 0x44a2b0, 0x2eb2b4, 0x54a950, 0x3cb559,
127 0x626b20, 0x4cad50, 0x385766, 0x5c5370, 0x484570, 0x326574, 0x5852b0, 0x406950, 0x2a7953, 0x505aa0,
128 0x3baaa7, 0x5ea6d0, 0x4a4ae0, 0x35a2e5, 0x5aa550, 0x42d2a0, 0x2de2a4, 0x52d550, 0x3e5abb, 0x6256a0,
129 0x4c96d0, 0x3949b6, 0x5e4ab0, 0x46a8d0, 0x30d4b5, 0x56b290, 0x40b550, 0x2a6d52, 0x504da0, 0x3b9567,
130 0x609570, 0x4a49b0, 0x34a975, 0x5a64b0, 0x446a90, 0x2cba94, 0x526b50, 0x3e2b60, 0x28ab61, 0x4c9570,
131 0x384ae6, 0x5cd160, 0x46e4a0, 0x2eed25, 0x54da90, 0x405b50, 0x2c36d3, 0x502ae0, 0x3a93d7, 0x6092d0,
132 0x4ac950, 0x32d556, 0x58b4a0, 0x42b690, 0x2e5d94, 0x5255b0, 0x3e25fa, 0x6425b0, 0x4e92b0, 0x36aab6,
133 0x5c6950, 0x4674a0, 0x31b2a5, 0x54ad50, 0x4055a0, 0x2aab73, 0x522570, 0x3a5377, 0x6052b0, 0x4a6950,
134 0x346d56, 0x585aa0, 0x42ab50, 0x2e56d4, 0x544ae0, 0x3ca570, 0x2864d2, 0x4cd260, 0x36eaa6, 0x5ad550,
135 0x465aa0, 0x30ada5, 0x5695d0, 0x404ad0, 0x2aa9b3, 0x50a4d0, 0x3ad2b7, 0x5eb250, 0x48b540, 0x33d556
136 ); /* Years 2100-2199 */
138 var CAN = new Array("Gi\341p", "\u1EA4t", "B\355nh", "\u0110inh", "M\u1EADu", "K\u1EF7", "Canh", "T\342n", "Nh\342m", "Qu\375");
139 var CHI = new Array("T\375", "S\u1EEDu", "D\u1EA7n", "Mão", "Th\354n", "T\u1EF5", "Ng\u1ECD", "M\371i", "Th\342n", "D\u1EADu", "Tu\u1EA5t", "H\u1EE3i");
140 var TUAN = new Array("Ch\u1EE7 Nh\u1EADt", "Th\u1EE9 Hai", "Th\u1EE9 Ba", "Th\u1EE9 T\u01B0", "Th\u1EE9 N\u0103m", "Th\u1EE9 S\341u", "Th\u1EE9 B\u1EA3y");
141 var GIO_HD = new Array("110100101100", "001101001011", "110011010010", "101100110100", "001011001101", "010010110011");
142 var TIETKHI = new Array("Xu\u00E2n ph\u00E2n", "Thanh minh", "C\u1ED1c v\u0169", "L\u1EADp h\u1EA1", "Ti\u1EC3u m\u00E3n", "Mang ch\u1EE7ng",
143 "H\u1EA1 ch\u00ED", "Ti\u1EC3u th\u1EED", "\u0110\u1EA1i th\u1EED", "L\u1EADp thu", "X\u1EED th\u1EED", "B\u1EA1ch l\u1ED9",
144 "Thu ph\u00E2n", "H\u00E0n l\u1ED9", "S\u01B0\u01A1ng gi\u00E1ng", "L\u1EADp \u0111\u00F4ng", "Ti\u1EC3u tuy\u1EBFt", "\u0110\u1EA1i tuy\u1EBFt",
145 "\u0110\u00F4ng ch\u00ED", "Ti\u1EC3u h\u00E0n", "\u0110\u1EA1i h\u00E0n", "L\u1EADp xu\u00E2n", "V\u0169 Th\u1EE7y", "Kinh tr\u1EADp"
150 /* Create lunar date object, stores (lunar) date, month, year, leap month indicator, and Julian date number */
151 function LunarDate(dd, mm, yy, leap, jd) {
161 /* Discard the fractional part of a number, e.g., INT(3.2) = 3 */
163 return Math.floor(d);
166 function jdn(dd, mm, yy) {
167 var a = INT((14 - mm) / 12);
170 var jd = dd + INT((153*m+2)/5) + 365*y + INT(y/4) - INT(y/100) + INT(y/400) - 32045;
172 //return 367*yy - INT(7*(yy+INT((mm+9)/12))/4) - INT(3*(INT((yy+(mm-9)/7)/100)+1)/4) + INT(275*mm/9)+dd+1721029;
175 function jdn2date(jd) {
176 var Z, A, alpha, B, C, D, E, dd, mm, yyyy, F;
181 alpha = INT((Z-1867216.25)/36524.25);
182 A = Z + 1 + alpha - INT(alpha/4);
185 C = INT( (B-122.1)/365.25);
187 E = INT( (B-D)/30.6001 );
188 dd = INT(B - D - INT(30.6001*E));
199 return new Array(dd, mm, yyyy);
202 function decodeLunarYear(yy, k) {
203 var monthLengths, regularMonths, offsetOfTet, leapMonth, leapMonthLength, solarNY, currentJD, j, mm;
204 var ly = new Array();
205 monthLengths = new Array(29, 30);
206 var regularMonths = new Array(12);
207 offsetOfTet = k >> 17;
209 leapMonthLength = monthLengths[k >> 16 & 0x1];
210 solarNY = jdn(1, 1, yy);
211 currentJD = solarNY+offsetOfTet;
213 for(var i = 0; i < 12; i++) {
214 regularMonths[12 - i - 1] = monthLengths[j & 0x1];
217 if (leapMonth == 0) {
218 for(mm = 1; mm <= 12; mm++) {
219 ly.push(new LunarDate(1, mm, yy, 0, currentJD));
220 currentJD += regularMonths[mm-1];
223 for(mm = 1; mm <= leapMonth; mm++) {
224 ly.push(new LunarDate(1, mm, yy, 0, currentJD));
225 currentJD += regularMonths[mm-1];
227 ly.push(new LunarDate(1, leapMonth, yy, 1, currentJD));
228 currentJD += leapMonthLength;
229 for(mm = leapMonth+1; mm <= 12; mm++) {
230 ly.push(new LunarDate(1, mm, yy, 0, currentJD));
231 currentJD += regularMonths[mm-1];
235 LML = leapMonthLength;
240 function leapMonth(yyyy){
241 var yearCode = getYearCode(yyyy);
242 return yearCode & 0xf;
245 function monthLength(yyyy){
246 var yearCode = getYearCode(yyyy);
247 return yearCode >> 16 & 0x1;
250 function getYearCode(yyyy){
253 yearCode = TK19[yyyy - 1800];
254 } else if (yyyy < 2000) {
255 yearCode = TK20[yyyy - 1900];
256 } else if (yyyy < 2100) {
257 yearCode = TK21[yyyy - 2000];
259 yearCode = TK22[yyyy - 2100];
264 function getYearInfo(yyyy) {
267 yearCode = TK19[yyyy - 1800];
268 } else if (yyyy < 2000) {
269 yearCode = TK20[yyyy - 1900];
270 } else if (yyyy < 2100) {
271 yearCode = TK21[yyyy - 2000];
273 yearCode = TK22[yyyy - 2100];
275 return decodeLunarYear(yyyy, yearCode);
278 var FIRST_DAY = jdn(25, 1, 1800); // Tet am lich 1800
279 var LAST_DAY = jdn(31, 12, 2199);
281 function findLunarDate(jd, ly) {
282 if (jd > LAST_DAY || jd < FIRST_DAY || ly[0].jd > jd) {
283 return new LunarDate(0, 0, 0, 0, jd);
286 while (jd < ly[i].jd) {
289 var off = jd - ly[i].jd;
290 var ret = new LunarDate(ly[i].day+off, ly[i].month, ly[i].year, ly[i].leap, jd);
294 function getLunarDate(dd, mm, yyyy) {
296 if (yyyy < 1800 || 2199 < yyyy) {
297 //return new LunarDate(0, 0, 0, 0, 0);
299 ly = getYearInfo(yyyy);
300 jd = jdn(dd, mm, yyyy);
302 ly = getYearInfo(yyyy - 1);
304 return findLunarDate(jd, ly);
307 /* Compute the longitude of the sun at any time.
308 * Parameter: floating number jdn, the number of days since 1/1/4713 BC noon
309 * Algorithm from: "Astronomical Algorithms" by Jean Meeus, 1998
311 function SunLongitude(jdn) {
312 var T, T2, dr, M, L0, DL, lambda, theta, omega;
313 T = (jdn - 2451545.0 ) / 36525; // Time in Julian centuries from 2000-01-01 12:00:00 GMT
315 dr = PI/180; // degree to radian
316 M = 357.52910 + 35999.05030*T - 0.0001559*T2 - 0.00000048*T*T2; // mean anomaly, degree
317 L0 = 280.46645 + 36000.76983*T + 0.0003032*T2; // mean longitude, degree
318 DL = (1.914600 - 0.004817*T - 0.000014*T2)*Math.sin(dr*M);
319 DL = DL + (0.019993 - 0.000101*T)*Math.sin(dr*2*M) + 0.000290*Math.sin(dr*3*M);
320 theta = L0 + DL; // true longitude, degree
321 // obtain apparent longitude by correcting for nutation and aberration
322 omega = 125.04 - 1934.136 * T;
323 lambda = theta - 0.00569 - 0.00478 * Math.sin(omega * dr);
324 // Convert to radians
326 lambda = lambda - PI*2*(INT(lambda/(PI*2))); // Normalize to (0, 2*PI)
330 /* Compute the sun segment at start (00:00) of the day with the given integral Julian day number.
331 * The time zone if the time difference between local time and UTC: 7.0 for UTC+7:00.
332 * The function returns a number between 0 and 23.
333 * From the day after March equinox and the 1st major term after March equinox, 0 is returned.
334 * After that, return 1, 2, 3 ...
336 function getSunLongitude(dayNumber, timeZone) {
337 return INT(SunLongitude(dayNumber - 0.5 - timeZone/24.0) / PI * 12);
340 var today = new Date();
341 //var currentLunarYear = getYearInfo(today.getFullYear());
342 var currentLunarDate = getLunarDate(today.getDate(), today.getMonth()+1, today.getFullYear());
343 var currentMonth = today.getMonth()+1;
344 var currentYear = today.getFullYear();
346 function parseQuery(q) {
347 var ret = new Array();
348 if (q.length < 2) return ret;
349 var s = q.substring(1, q.length);
350 var arr = s.split("&");
352 for (i = 0; i < arr.length; i++) {
353 var a = arr[i].split("=");
354 for (j = 0; j < a.length; j++) {
361 function getSelectedMonth() {
362 var query = window.location.search;
363 var arr = parseQuery(query);
365 for (idx = 0; idx < arr.length; idx++) {
366 if (arr[idx] == "mm") {
367 currentMonth = parseInt(arr[idx+1]);
368 } else if (arr[idx] == "yy") {
369 currentYear = parseInt(arr[idx+1]);
374 function getMonth(mm, yy) {
375 var ly1, ly2, tet1, jd1, jd2, mm1, yy1, result, i;
383 jd1 = jdn(1, mm, yy);
384 jd2 = jdn(1, mm1, yy1);
385 ly1 = getYearInfo(yy);
386 //alert('1/'+mm+'/'+yy+' = '+jd1+'; 1/'+mm1+'/'+yy1+' = '+jd2);
388 result = new Array();
389 if (tet1 <= jd1) { /* tet(yy) = tet1 < jd1 < jd2 <= 1.1.(yy+1) < tet(yy+1) */
390 for (i = jd1; i < jd2; i++) {
391 result.push(findLunarDate(i, ly1));
393 } else if (jd1 < tet1 && jd2 < tet1) { /* tet(yy-1) < jd1 < jd2 < tet1 = tet(yy) */
394 ly1 = getYearInfo(yy - 1);
395 for (i = jd1; i < jd2; i++) {
396 result.push(findLunarDate(i, ly1));
398 } else if (jd1 < tet1 && tet1 <= jd2) { /* tet(yy-1) < jd1 < tet1 <= jd2 < tet(yy+1) */
399 ly2 = getYearInfo(yy - 1);
400 for (i = jd1; i < tet1; i++) {
401 result.push(findLunarDate(i, ly2));
403 for (i = tet1; i < jd2; i++) {
404 result.push(findLunarDate(i, ly1));
410 function getDayName(lunarDate) {
411 if (lunarDate.day == 0) {
414 var cc = getCanChi(lunarDate);
415 var s = "Ng\u00E0y " + cc[0] +", th\341ng "+cc[1] + ", n\u0103m " + cc[2];
419 function getYearCanChi(year) {
420 return CAN[(year+6) % 10] + " " + CHI[(year+8) % 12];
424 * Can cua gio Chinh Ty (00:00) cua ngay voi JDN nay
426 function getCanHour0(jdn) {
427 return CAN[(jdn-1)*2 % 10];
430 function getCanChi(lunar) {
431 var dayName, monthName, yearName;
432 dayName = CAN[(lunar.jd + 9) % 10] + " " + CHI[(lunar.jd+1)%12];
433 monthName = CAN[(lunar.year*12+lunar.month+3) % 10] + " " + CHI[(lunar.month+1)%12];
434 if (lunar.leap == 1) {
437 yearName = getYearCanChi(lunar.year);
438 return new Array(dayName, monthName, yearName);
441 function getDayString(lunar, solarDay, solarMonth, solarYear) {
443 var dayOfWeek = TUAN[(lunar.jd + 1) % 7];
444 s = dayOfWeek + " " + solarDay + "/" + solarMonth + "/" + solarYear;
446 s = s + "Ng\u00E0y " + lunar.day+" th\341ng "+lunar.month;
447 if (lunar.leap == 1) {
448 s = s + " nhu\u1EADn";
453 function getTodayString() {
454 var s = getDayString(currentLunarDate, today.getDate(), today.getMonth()+1, today.getFullYear());
455 s += " n\u0103m " + getYearCanChi(currentLunarDate.year);
459 function getCurrentTime() {
461 var Std = today.getHours();
462 var Min = today.getMinutes();
463 var Sec = today.getSeconds();
464 var s1 = ((Std < 10) ? "0" + Std : Std);
465 var s2 = ((Min < 10) ? "0" + Min : Min);
466 //var s3 = ((Sec < 10) ? "0" + Sec : Sec);
467 //return s1 + ":" + s2 + ":" + s3;
468 return s1 + ":" + s2;
471 function getGioHoangDao(jd) {
472 var chiOfDay = (jd+1) % 12;
473 var gioHD = GIO_HD[chiOfDay % 6]; // same values for Ty' (1) and Ngo. (6), for Suu and Mui etc.
476 for (var i = 0; i < 12; i++) {
477 if (gioHD.charAt(i) == '1') {
479 ret += ' ('+(i*2+23)%24+'h-'+(i*2+1)%24+'h)';
480 if (count++ < 5) ret += ', ';
481 if (count == 3) ret += '<br>';
488 return TUAN[(jd+1)%7];
491 function getTHUINT(jd){