1//--------------------- Copyright Block ---------------------- 2/* 3 4PrayTimes.js: Prayer Times Calculator (ver 2.3) 5Copyright (C) 2007-2011 PrayTimes.org 6 7Developer: Hamid Zarrabi-Zadeh 8License: GNU LGPL v3.0 9 10TERMS OF USE: 11 Permission is granted to use this code, with or 12 without modification, in any website or application 13 provided that credit is given to the original work 14 with a link back to PrayTimes.org. 15 16This program is distributed in the hope that it will 17be useful, but WITHOUT ANY WARRANTY. 18 19PLEASE DO NOT REMOVE THIS COPYRIGHT BLOCK. 20 21*/ 22 23//--------------------- Help and Manual ---------------------- 24/* 25 26User's Manual: 27http://praytimes.org/manual 28 29Calculation Formulas: 30http://praytimes.org/calculation 31 32 33 34//------------------------ User Interface ------------------------- 35 36 37 getTimes (date, coordinates [, timeZone [, dst [, timeFormat]]]) 38 39 setMethod (method) // set calculation method 40 adjust (parameters) // adjust calculation parameters 41 tune (offsets) // tune times by given offsets 42 43 getMethod () // get calculation method 44 getSetting () // get current calculation parameters 45 getOffsets () // get current time offsets 46 47 48//------------------------- Sample Usage -------------------------- 49 50 51 var PT = new PrayTimes('ISNA'); 52 var times = PT.getTimes(new Date(), [43, -80], -5); 53 document.write('Sunrise = '+ times.sunrise) 54 55 56*/ 57 58 59//----------------------- PrayTimes Class ------------------------ 60 61 62function PrayTimes(method) { 63 64 65 //------------------------ Constants -------------------------- 66 var 67 68 // Time Names 69 timeNames = { 70 imsak : 'Imsak', 71 fajr : 'Fajr', 72 sunrise : 'Sunrise', 73 dhuhr : 'Dhuhr', 74 asr : 'Asr', 75 sunset : 'Sunset', 76 maghrib : 'Maghrib', 77 isha : 'Isha', 78 midnight : 'Midnight' 79 }, 80 81 82 // Calculation Methods 83 methods = { 84 MWL: { 85 name: 'Muslim World League', 86 params: { fajr: 18, isha: 17 } }, 87 ISNA: { 88 name: 'Islamic Society of North America (ISNA)', 89 params: { fajr: 15, isha: 15 } }, 90 Egypt: { 91 name: 'Egyptian General Authority of Survey', 92 params: { fajr: 19.5, isha: 17.5 } }, 93 Makkah: { 94 name: 'Umm Al-Qura University, Makkah', 95 params: { fajr: 18.5, isha: '90 min' } }, // fajr was 19 degrees before 1430 hijri 96 Karachi: { 97 name: 'University of Islamic Sciences, Karachi', 98 params: { fajr: 18, isha: 18 } }, 99 Tehran: { 100 name: 'Institute of Geophysics, University of Tehran', 101 params: { fajr: 17.7, isha: 14, maghrib: 4.5, midnight: 'Jafari' } }, // isha is not explicitly specified in this method 102 Jafari: { 103 name: 'Shia Ithna-Ashari, Leva Institute, Qum', 104 params: { fajr: 16, isha: 14, maghrib: 4, midnight: 'Jafari' } } 105 }, 106 107 108 // Default Parameters in Calculation Methods 109 defaultParams = { 110 maghrib: '0 min', midnight: 'Standard' 111 112 }, 113 114 115 //----------------------- Parameter Values ---------------------- 116 /* 117 118 // Asr Juristic Methods 119 asrJuristics = [ 120 'Standard', // Shafi`i, Maliki, Ja`fari, Hanbali 121 'Hanafi' // Hanafi 122 ], 123 124 125 // Midnight Mode 126 midnightMethods = [ 127 'Standard', // Mid Sunset to Sunrise 128 'Jafari' // Mid Sunset to Fajr 129 ], 130 131 132 // Adjust Methods for Higher Latitudes 133 highLatMethods = [ 134 'NightMiddle', // middle of night 135 'AngleBased', // angle/60th of night 136 'OneSeventh', // 1/7th of night 137 'None' // No adjustment 138 ], 139 140 141 // Time Formats 142 timeFormats = [ 143 '24h', // 24-hour format 144 '12h', // 12-hour format 145 '12hNS', // 12-hour format with no suffix 146 'Float' // floating point number 147 ], 148 */ 149 150 151 //---------------------- Default Settings -------------------- 152 153 calcMethod = 'MWL', 154 155 // do not change anything here; use adjust method instead 156 setting = { 157 imsak : '10 min', 158 dhuhr : '0 min', 159 asr : 'Standard', 160 highLats : 'NightMiddle' 161 }, 162 163 timeFormat = '24h', 164 timeSuffixes = ['am', 'pm'], 165 invalidTime = '-----', 166 167 numIterations = 1, 168 offset = {}, 169 170 171 //----------------------- Local Variables --------------------- 172 173 lat, lng, elv, // coordinates 174 timeZone, jDate; // time variables 175 176 177 //---------------------- Initialization ----------------------- 178 179 180 // set methods defaults 181 var defParams = defaultParams; 182 for (var i in methods) { 183 var params = methods[i].params; 184 for (var j in defParams) 185 if ((typeof(params[j]) == 'undefined')) 186 params[j] = defParams[j]; 187 }; 188 189 // initialize settings 190 calcMethod = methods[method] ? method : calcMethod; 191 var params = methods[calcMethod].params; 192 for (var id in params) 193 setting[id] = params[id]; 194 195 // init time offsets 196 for (var i in timeNames) 197 offset[i] = 0; 198 199 200 201 //----------------------- Public Functions ------------------------ 202 return { 203 204 205 // set calculation method 206 setMethod: function(method) { 207 if (methods[method]) { 208 this.adjust(methods[method].params); 209 calcMethod = method; 210 } 211 }, 212 213 214 // set calculating parameters 215 adjust: function(params) { 216 for (var id in params) 217 setting[id] = params[id]; 218 }, 219 220 221 // set time offsets
222 tune: function(timeOffsets) { 223 for (var i in timeOffsets) 224 offset[i] = timeOffsets[i]; 225 }, 226 227 228 // get current calculation method 229 getMethod: function() { return calcMethod; }, 230 231 // get current setting 232 getSetting: function() { return setting; }, 233 234 // get current time offsets 235 getOffsets: function() { return offset; }, 236 237 // get default calc parametrs 238 getDefaults: function() { return methods; }, 239 240 241 // return prayer times for a given date 242 getTimes: function(date, coords, timezone, dst, format) { 243 lat = 1* coords[0]; 244 lng = 1* coords[1]; 245 elv = coords[2] ? 1* coords[2] : 0; 246 timeFormat = format || timeFormat; 247 if (date.constructor === Date) 248 date = [date.getFullYear(), date.getMonth()+ 1, date.getDate()]; 249 if (typeof(timezone) == 'undefined' || timezone == 'auto') 250 timezone = this.getTimeZone(date); 251 if (typeof(dst) == 'undefined' || dst == 'auto') 252 dst = this.getDst(date); 253 timeZone = 1* timezone+ (1* dst ? 1 : 0); 254 jDate = this.julian(date[0], date[1], date[2])- lng/ (15* 24); 255 256 return this.computeTimes(); 257 }, 258 259 260 // convert float time to the given format (see timeFormats) 261 getFormattedTime: function(time, format, suffixes) { 262 if (isNaN(time)) 263 return invalidTime; 264 if (format == 'Float') return time; 265 suffixes = suffixes || timeSuffixes; 266 267 time = DMath.fixHour(time+ 0.5/ 60); // add 0.5 minutes to round 268 var hours = Math.floor(time); 269 var minutes = Math.floor((time- hours)* 60); 270 var suffix = (format == '12h') ? suffixes[hours < 12 ? 0 : 1] : ''; 271 var hour = (format == '24h') ? this.twoDigitsFormat(hours) : ((hours+ 12 -1)% 12+ 1); 272 return hour+ ':'+ this.twoDigitsFormat(minutes)+ (suffix ? ' '+ suffix : ''); 273 }, 274 275 276 //---------------------- Calculation Functions ----------------------- 277 278 279 // compute mid-day time 280 midDay: function(time) { 281 var eqt = this.sunPosition(jDate + time).equation; 282 var noon = DMath.fixHour(12- eqt); 283 return noon; 284 }, 285 286 287 // compute the time at which sun reaches a specific angle below horizon 288 sunAngleTime: function(angle, time, direction) { 289 var decl = this.sunPosition(jDate + time).declination; 290 var noon = this.midDay(time); 291 var t = 1/15* DMath.arccos((-DMath.sin(angle)- DMath.sin(decl)* DMath.sin(lat))/ 292 (DMath.cos(decl)* DMath.cos(lat))); 293 return noon+ (direction == 'ccw' ? -t : t); 294 }, 295 296 297 // compute asr time 298 asrTime: function(factor, time) { 299 var decl = this.sunPosition(jDate + time).declination; 300 var angle = -DMath.arccot(factor+ DMath.tan(Math.abs(lat- decl))); 301 return this.sunAngleTime(angle, time); 302 }, 303 304 305 // compute declination angle of sun and equation of time 306 // Ref: http://aa.usno.navy.mil/faq/docs/SunApprox.php 307 sunPosition: function(jd) { 308 var D = jd - 2451545.0; 309 var g = DMath.fixAngle(357.529 + 0.98560028* D); 310 var q = DMath.fixAngle(280.459 + 0.98564736* D); 311 var L = DMath.fixAngle(q + 1.915* DMath.sin(g) + 0.020* DMath.sin(2*g)); 312 313 var R = 1.00014 - 0.01671* DMath.cos(g) - 0.00014* DMath.cos(2*g); 314 var e = 23.439 - 0.00000036* D; 315 316 var RA = DMath.arctan2(DMath.cos(e)* DMath.sin(L), DMath.cos(L))/ 15; 317 var eqt = q/15 - DMath.fixHour(RA); 318 var decl = DMath.arcsin(DMath.sin(e)* DMath.sin(L)); 319 320 return {declination: decl, equation: eqt}; 321 }, 322 323 324 // convert Gregorian date to Julian day 325 // Ref: Astronomical Algorithms by Jean Meeus 326 julian: function(year, month, day) { 327 if (month <= 2) { 328 year -= 1; 329 month += 12; 330 }; 331 var A = Math.floor(year/ 100); 332 var B = 2- A+ Math.floor(A/ 4); 333 334 var JD = Math.floor(365.25* (year+ 4716))+ Math.floor(30.6001* (month+ 1))+ day+ B- 1524.5; 335 return JD; 336 }, 337 338 339 //---------------------- Compute Prayer Times ----------------------- 340 341 342 // compute prayer times at given julian date 343 computePrayerTimes: function(times) { 344 times = this.dayPortion(times); 345 var params = setting; 346 347 var imsak = this.sunAngleTime(this.eval(params.imsak), times.imsak, 'ccw'); 348 var fajr = this.sunAngleTime(this.eval(params.fajr), times.fajr, 'ccw'); 349 var sunrise = this.sunAngleTime(this.riseSetAngle(), times.sunrise, 'ccw'); 350 var dhuhr = this.midDay(times.dhuhr); 351 var asr = this.asrTime(this.asrFactor(params.asr), times.asr); 352 var sunset = this.sunAngleTime(this.riseSetAngle(), times.sunset);; 353 var maghrib = this.sunAngleTime(this.eval(params.maghrib), times.maghrib); 354 var isha = this.sunAngleTime(this.eval(params.isha), times.isha); 355 356 return { 357 imsak: imsak, fajr: fajr, sunrise: sunrise, dhuhr: dhuhr, 358 asr: asr, sunset: sunset, maghrib: maghrib, isha: isha 359 }; 360 }, 361 362 363 // compute prayer times 364 computeTimes: function() { 365 // default times 366 var times = { 367 imsak: 5, fajr: 5, sunrise: 6, dhuhr: 12, 368 asr: 13, sunset: 18, maghrib: 18, isha: 18 369 }; 370 371 // main iterations 372 for (var i=1 ; i<=numIterations ; i++) 373 times = this.computePrayerTimes(times); 374 375 times = this.adjustTimes(times); 376 377 // add midnight time 378 times.midnight = (setting.midnight == 'Jafari') ? 379 times.sunset+ this.timeDiff(times.sunset, times.fajr)/ 2 : 380 times.sunset+ this.timeDiff(times.sunset, times.sunrise)/ 2; 381 382 times = this.tuneTimes(times); 383 return this.modifyFormats(times); 384 }, 385 386 387 // adjust times 388 adjustTimes: function(times) { 389 var params = setting; 390 for (var i in times) 391 times[i] += timeZone- lng/ 15; 392 393 if (params.highLats != 'None') 394 times = this.adjustHighLats(times); 395 396 if (this.isMin(params.imsak)) 397 times.imsak = times.fajr- this.eval(params.imsak)/ 60; 398 if (this.isMin(params.maghrib)) 399 times.maghrib = times.sunset+ this.eval(params.maghrib)/ 60; 400 if (this.isMin(params.isha)) 401 times.isha = times.maghrib+ this.eval(params.isha)/ 60; 402 times.dhuhr += this.eval(params.dhuhr)/ 60; 403 404 return times; 405 }, 406 407 408 // get asr shadow factor 409 asrFactor: function(asrParam) { 410 var factor = {Standard: 1, Hanafi: 2}[asrParam]; 411 return factor || this.eval(asrParam); 412 }, 413 414 415 // return sun angle for sunset/sunrise 416 riseSetAngle: function() { 417 //var earthRad = 6371009; // in meters 418 //var angle = DMath.arccos(earthRad/(earthRad+ elv)); 419 var angle = 0.0347* Math.sqrt(elv); // an approximation 420 return 0.833+ angle; 421 }, 422 423 424 // apply offsets to the times 425 tuneTimes: function(times) { 426 for (var i in times) 427 times[i] += offset[i]/ 60; 428 return times; 429 }, 430 431 432 // convert times to given time format 433 modifyFormats: function(times) { 434 for (var i in times) 435 times[i] = this.getFormattedTime(times[i], timeFormat); 436 return times; 437 }, 438 439 440 // adjust times for locations in higher latitudes 441 adjustHighLats: function(times) { 442 var params = setting; 443 var nightTime = this.timeDiff(times.sunset, times.sunrise); 444 445 times.imsak = this.adjustHLTime(times.imsak, times.sunrise, this.eval(params.imsak), nightTime, 'ccw'); 446 times.fajr = this.adjustHLTime(times.fajr, times.sunrise, this.eval(params.fajr), nightTime, 'ccw'); 447 times.isha = this.adjustHLTime(times.isha, times.sunset, this.eval(params.isha), nightTime); 448 times.maghrib = this.adjustHLTime(times.maghrib, times.sunset, this.eval(params.maghrib), nightTime); 449 450 return times; 451 }, 452 453
454 // adjust a time for higher latitudes 455 adjustHLTime: function(time, base, angle, night, direction) { 456 var portion = this.nightPortion(angle, night); 457 var timeDiff = (direction == 'ccw') ? 458 this.timeDiff(time, base): 459 this.timeDiff(base, time); 460 if (isNaN(time) || timeDiff > portion) 461 time = base+ (direction == 'ccw' ? -portion : portion); 462 return time; 463 }, 464 465 466 // the night portion used for adjusting times in higher latitudes 467 nightPortion: function(angle, night) { 468 var method = setting.highLats; 469 var portion = 1/2 // MidNight 470 if (method == 'AngleBased') 471 portion = 1/60* angle; 472 if (method == 'OneSeventh') 473 portion = 1/7; 474 return portion* night; 475 }, 476 477 478 // convert hours to day portions 479 dayPortion: function(times) { 480 for (var i in times) 481 times[i] /= 24; 482 return times; 483 }, 484 485 486 //---------------------- Time Zone Functions ----------------------- 487 488 489 // get local time zone 490 getTimeZone: function(date) { 491 var year = date[0]; 492 var t1 = this.gmtOffset([year, 0, 1]); 493 var t2 = this.gmtOffset([year, 6, 1]); 494 return Math.min(t1, t2); 495 }, 496 497 498 // get daylight saving for a given date 499 getDst: function(date) { 500 return 1* (this.gmtOffset(date) != this.getTimeZone(date)); 501 }, 502 503 504 // GMT offset for a given date 505 gmtOffset: function(date) { 506 var localDate = new Date(date[0], date[1]- 1, date[2], 12, 0, 0, 0); 507 var GMTString = localDate.toGMTString(); 508 var GMTDate = new Date(GMTString.substring(0, GMTString.lastIndexOf(' ')- 1)); 509 var hoursDiff = (localDate- GMTDate) / (1000* 60* 60); 510 return hoursDiff; 511 }, 512 513 514 //---------------------- Misc Functions ----------------------- 515 516 // convert given string into a number 517 eval: function(str) { 518 return 1* (str+ '').split(/[^0-9.+-]/)[0]; 519 }, 520 521 522 // detect if input contains 'min' 523 isMin: function(arg) { 524 return (arg+ '').indexOf('min') != -1; 525 }, 526 527 528 // compute the difference between two times 529 timeDiff: function(time1, time2) { 530 return DMath.fixHour(time2- time1); 531 }, 532 533 534 // add a leading 0 if necessary 535 twoDigitsFormat: function(num) { 536 return (num <10) ? '0'+ num : num; 537 } 538 539}}; 540 541 542 543//---------------------- Degree-Based Math Class ----------------------- 544 545 546var DMath = { 547 548 dtr: function(d) { return (d * Math.PI) / 180.0; }, 549 rtd: function(r) { return (r * 180.0) / Math.PI; }, 550 551 sin: function(d) { return Math.sin(this.dtr(d)); }, 552 cos: function(d) { return Math.cos(this.dtr(d)); }, 553 tan: function(d) { return Math.tan(this.dtr(d)); }, 554 555 arcsin: function(d) { return this.rtd(Math.asin(d)); }, 556 arccos: function(d) { return this.rtd(Math.acos(d)); }, 557 arctan: function(d) { return this.rtd(Math.atan(d)); }, 558 559 arccot: function(x) { return this.rtd(Math.atan(1/x)); }, 560 arctan2: function(y, x) { return this.rtd(Math.atan2(y, x)); }, 561 562 fixAngle: function(a) { return this.fix(a, 360); }, 563 fixHour: function(a) { return this.fix(a, 24 ); }, 564 565 fix: function(a, b) { 566 a = a- b* (Math.floor(a/ b)); 567 return (a < 0) ? a+ b : a; 568 } 569};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.