All files / calendrica-js/src persian.js

91.17% Statements 31/34
75% Branches 9/12
87.5% Functions 7/8
90.62% Lines 29/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 7024x 24x 24x 24x     24x     24x               387x   24x 24x   24x   24x       354x       1x 99x 99x 255x         1x 66x     66x       1x 33x 33x 33x 33x 33x     33x 33x       1x             24x  
const { fixedFromJulian } = require( './julian' )
const { MARCH, gregorianYearFromFixed } = require( './gregorian' )
const { MEAN_TROPICAL_YEAR, estimatePriorSolarLongitude, midday, solarLongitude } = require( './astronomy' )
const { hr, next } = require( './general' )
 
// Fixed date of start of the Persian calendar.
const PERSIAN_EPOCH = fixedFromJulian( 622, MARCH, 19 )
 
// Location of Tehran, Iran.
const TEHRAN = {
  latitude: 35.68,
  longitude: 51.42,
  elevation: 1100,
  zone: hr( 3 + 1 / 2 ),
}
 
// Universal time of true noon on fixed $date$ in Tehran.
const middayInTehran = date => midday( date, TEHRAN )
 
const Persian = class {
  static PERSIAN_EPOCH = PERSIAN_EPOCH
 
  static TEHRAN = TEHRAN
 
  static middayInTehran = middayInTehran
 
  // Set location for midday calculation
  constructor( LOCATION ) {
    this.midday = date => ( LOCATION ? midday( date, LOCATION ) : middayInTehran( date ) )
  }
 
  // Fixed date of Astronomical Persian New Year on or before fixed date.
  persianNewYearOnOrBefore = date => {
    const approx = estimatePriorSolarLongitude( 0, this.midday( date ) )
    return next( Math.floor( approx ) - 1, day => (
      solarLongitude( this.midday( day ) ) <= 0 + 2
    ) )
  }
 
  // Fixed date of Astronomical Persian date p-date.
  fixedFromPersian = ( year, month, day ) => {
    const newYear = this.persianNewYearOnOrBefore(
      PERSIAN_EPOCH + 180 + Math.floor( MEAN_TROPICAL_YEAR * ( year > 0 ? year - 1 : year ) ),
    )
    return newYear - 1 + ( month <= 7 ? 31 * ( month - 1 ) : 30 * ( month - 1 ) + 6 ) + day
  }
 
  // Astronomical Persian date (year month day) corresponding to fixed date.
  persianFromFixed = date => {
    const newYear = this.persianNewYearOnOrBefore( date )
    const y = Math.round( ( newYear - PERSIAN_EPOCH ) / MEAN_TROPICAL_YEAR ) + 1
    const year = y > 0 ? y : y - 1
    const dayOfYear = date - this.fixedFromPersian( year, 1, 1 ) + 1
    const month = dayOfYear <= 186
      ? Math.ceil( ( 1 / 31 ) * dayOfYear )
      : Math.ceil( ( 1 / 30 ) * ( dayOfYear - 6 ) )
    const day = date - this.fixedFromPersian( year, month, 1 ) + 1
    return { year, month, day }
  }
 
  // Fixed date of Persian New Year (Nowruz) in Gregorian year g-year.
  nowruz = gYear => {
    const persianYear = gYear - gregorianYearFromFixed( PERSIAN_EPOCH ) + 1
    const y = persianYear <= 0 ? persianYear - 1 : persianYear
    return this.fixedFromPersian( y, 1, 1 )
  }
}
 
module.exports = Persian