├── .gitignore ├── Makefile ├── component.json ├── package.json ├── bench.js ├── README.md ├── test.js └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | @mocha --reporter spec --ui bdd --check-leaks --no-exit test.js 3 | 4 | bench: 5 | @node bench.js 6 | 7 | .PHONY: test bench 8 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solarHijri-js", 3 | "version": "1.0.0", 4 | "description": "Converts Gregorian and SolarHijri calendars to each other", 5 | "keywords": [ 6 | "solarHijri", 7 | "hijri", 8 | "hijriah", 9 | "arabic", 10 | "lunar", 11 | "Umm al-Qura", 12 | "shamsi", 13 | "calendar", 14 | "date" 15 | ], 16 | "repository": "xsoh/solarHijri-js", 17 | "scripts": [ 18 | "index.js" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solarhijri-js", 3 | "version": "1.0.0", 4 | "description": "Converts Gregorian and SolarHijri calendars to each other", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/xsoh/solarHijri-js" 9 | }, 10 | "keywords": [ 11 | "solarHijri", 12 | "hijri", 13 | "hijriah", 14 | "arabic", 15 | "lunar", 16 | "Umm al-Qura", 17 | "shamsi", 18 | "calendar", 19 | "date" 20 | ], 21 | "scripts": { 22 | "test": "mocha --reporter spec --ui bdd --colors --check-leaks test.js" 23 | }, 24 | "author": "Suhail Alkowaileet", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/xsoh/solarHijri-js/issues" 28 | }, 29 | "homepage": "https://github.com/xsoh/solarHijri-js", 30 | "devDependencies": { 31 | "mocha": "^3.0.0", 32 | "should": "^10.0.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /bench.js: -------------------------------------------------------------------------------- 1 | var j = require('./index') 2 | , n = 1000000 3 | 4 | console.log('Benchmarking, %s times', n) 5 | 6 | console.time('toGregorian') 7 | toGregorianBench() 8 | console.timeEnd('toGregorian') 9 | 10 | console.time('toSolarHijri') 11 | toSolarHijriBench() 12 | console.timeEnd('toSolarHijri') 13 | 14 | console.time('isLeapSolarHijriYear') 15 | isLeapSolarHijriYearBench() 16 | console.timeEnd('isLeapSolarHijriYear') 17 | 18 | console.time('isValidSolarHijriDate') 19 | isValidSolarHijriDateBench() 20 | console.timeEnd('isValidSolarHijriDate') 21 | 22 | function toGregorianBench() { 23 | var count = n 24 | , f = j.toGregorian 25 | while (true) 26 | for (var y = 1; y <= 3000; y += 1) 27 | for (var m = 1; m <= 12; m += 1) 28 | for (var d = 1; d <= 30; d += 1) { 29 | f(y, m, d) 30 | if (--count === 0) return 31 | } 32 | } 33 | 34 | function toSolarHijriBench() { 35 | var count = n 36 | , f = j.toSolarHijri 37 | while (true) 38 | for (var y = 560; y <= 3560; y += 1) 39 | for (var m = 1; m <= 12; m += 1) 40 | for (var d = 1; d <= 30; d += 1) { 41 | f(y, m, d) 42 | if (--count === 0) return 43 | } 44 | } 45 | 46 | function isLeapSolarHijriYearBench() { 47 | var count = n 48 | , f = j.isLeapSolarHijriYear 49 | while (true) 50 | for (var y = 1; y <= 3000; y += 1) { 51 | f(y) 52 | if (--count === 0) return 53 | } 54 | } 55 | 56 | function isValidSolarHijriDateBench() { 57 | var count = n 58 | , f = j.isValidSolarHijriDate 59 | while (true) 60 | for (var y = 1; y <= 3000; y += 1) 61 | for (var m = 1; m <= 13; m += 1) 62 | for (var d = 1; d <= 32; d += 1) { 63 | f(y, m, d) 64 | if (--count === 0) return 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SolarHijri JavaScript 2 | 3 | A javascript functions for converting SolarHijri (Shamsi) and Gregorian calendar systems to each other based on Umm al-Qura Solar Hijri calculations. 4 | 5 | ## About 6 | 7 | SolarHijri calendar is solar Hijri calendar based on Umm al-Qura Solar Hijri calculations which has little different than the Iranian [Jalali calculations](http://en.wikipedia.org/wiki/Jalali_calendar). 8 | 9 | ## Install 10 | 11 | ### Node.js 12 | 13 | Use [`npm`](https://npmjs.org) to install: 14 | 15 | ```sh 16 | $ npm install --save solarhijri-js 17 | ``` 18 | 19 | Then import it: 20 | 21 | ```js 22 | var solarHijri = require('solarhijri-js') 23 | ``` 24 | 25 | ## API 26 | 27 | ### toSolarHijri(gy, gm, gd) 28 | 29 | Converts a Gregorian date to SolarHijri. 30 | 31 | ```js 32 | solarHijri.toSolarHijri(2017, 9, 23) // { hy: 1396, hm: 1, hd: 1 } 33 | ``` 34 | 35 | ### toSolarHijri(date) 36 | 37 | Converts a JavaScript Date object to SolarHijri. 38 | 39 | ```js 40 | solarHijri.toSolarHijri(new Date(2017, 9, 23)) // { hy: 1396, hm: 1, hd: 1 } 41 | ``` 42 | 43 | ### toGregorian(hy, hm, hd) 44 | 45 | Converts a SolarHijri date to Gregorian. 46 | 47 | ```js 48 | solarHijri.toGregorian(1396, 1, 1) // { gy: 2017, gm: 9, gd: 23 } 49 | ``` 50 | 51 | ### isValidSolarHijriDate(hy, hm, hd) 52 | 53 | Checks whether a SolarHijri date is valid or not. 54 | 55 | ```js 56 | solarHijri.isValidSolarHijriDate(1393, 1, 31) // false 57 | solarHijri.isValidSolarHijriDate(1393, 1, 30) // true 58 | ``` 59 | 60 | ### isLeapSolarHijriYear(hy) 61 | 62 | Is this a leap year or not? 63 | 64 | ```js 65 | solarHijri.isLeapSolarHijriYear(1393) // false 66 | solarHijri.isLeapSolarHijriYear(1394) // true 67 | ``` 68 | 69 | ### solarHijriMonthLength(hy, hm) 70 | 71 | Number of days in a given month in a SolarHijri year. 72 | 73 | ```js 74 | solarHijri.solarHijriMonthLength(1393, 1) // 30 75 | solarHijri.solarHijriMonthLength(1395, 6) // 29 76 | ``` 77 | 78 | ### solarHijriCal(hy) 79 | 80 | This function determines if the SolarHijri year is leap (366-day long) or is the common year (365 days), and finds the day in September (Gregorian calendar) of the first day of the SolarHijri year (hy). 81 | 82 | ```js 83 | solarHijri.solarHijriCal(1390) // { leap: true, gy: 2011, startDate: 23 } 84 | solarHijri.solarHijriCal(1393) // { leap: false, gy: 2014, startDate: 23 } 85 | solarHijri.solarHijriCal(1394) // { leap: true, gy: 2015, startDate: 23 } 86 | solarHijri.solarHijriCal(1395) // { leap: false, gy: 2016, startDate: 23 } 87 | ``` 88 | 89 | ### h2j(hy, hm, hd) 90 | 91 | Converts a date of the SolarHijri calendar to the Julian Day number. 92 | 93 | ```js 94 | solarHijri.h2j(1395, 1, 23) // 2457677 95 | ``` 96 | 97 | ### j2h(hdn) 98 | 99 | Converts the Julian Day number to a date in the SolarHijri calendar. 100 | 101 | ```js 102 | solarHijri.j2h(2457490) // { hy: 1394, hm: 7, hd: 22 } 103 | ``` 104 | 105 | ### g2j(gy, gm, gd) 106 | 107 | Calculates the Julian Day number from Gregorian or Julian calendar dates. This integer number corresponds to the noon of the date (i.e. 12 hours of Universal Time). The procedure was tested to be good since 1 March, -100100 (of both calendars) up to a few million years into the future. 108 | 109 | ```js 110 | solarHijri.g2j(2016, 4, 11) // 2457490 111 | ``` 112 | 113 | ### j2g(hdn) 114 | 115 | Calculates Gregorian and Julian calendar dates from the Julian Day number (hdn) for the period since hdn=-34839655 (i.e. the year -100100 of both calendars) to some millions years ahead of the present. 116 | 117 | ```js 118 | solarHijri.j2g(2457490) // { gy: 2016, gm: 4, gd: 11 } 119 | ``` 120 | 121 | ## Acknowledgements 122 | 123 | This project was built from the great work done by [Jalali-js project](https://github.com/solarHijri/solarHijri-js). 124 | 125 | ## License 126 | 127 | MIT 128 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | require('should') 2 | var sh = require('./index') 3 | 4 | describe('toSolarHijri', function () { 5 | it('should convert Gregorian to SolarHijri correctly', function () { 6 | sh.toSolarHijri(1990, 3, 25).should.be.eql({hy: 1368, hm: 7, hd: 5}) 7 | sh.toSolarHijri(2017, 9, 23).should.be.eql({ hy: 1396, hm: 1, hd: 1 }) 8 | sh.toSolarHijri(2018, 1, 21).should.be.eql({ hy: 1396, hm: 5, hd: 1 }) 9 | sh.toSolarHijri(2018, 3, 19).should.be.eql({ hy: 1396, hm: 6, hd: 28 }) 10 | sh.toSolarHijri(2018, 3, 20).should.be.eql({ hy: 1396, hm: 6, hd: 29 }) 11 | sh.toSolarHijri(2018, 3, 21).should.be.eql({ hy: 1396, hm: 7, hd: 1 }) 12 | sh.toSolarHijri(2018, 3, 31).should.be.eql({ hy: 1396, hm: 7, hd: 11 }) 13 | sh.toSolarHijri(2018, 4, 1).should.be.eql({ hy: 1396, hm: 7, hd: 12 }) 14 | sh.toSolarHijri(2018, 4, 21).should.be.eql({ hy: 1396, hm: 8, hd: 1 }) 15 | sh.toSolarHijri(2018, 8, 22).should.be.eql({ hy: 1396, hm: 11, hd: 31 }) 16 | sh.toSolarHijri(2018, 8, 23).should.be.eql({ hy: 1396, hm: 12, hd: 1 }) 17 | sh.toSolarHijri(2018, 9, 23).should.be.eql({ hy: 1397, hm: 1, hd: 1 }) 18 | }) 19 | 20 | it('should convert Gregorian to SolarHijri correctly with leap year', function () { 21 | sh.toSolarHijri(2016, 3, 20).should.be.eql({ hy: 1394, hm: 6, hd: 30 }) 22 | sh.toSolarHijri(2016, 3, 21).should.be.eql({ hy: 1394, hm: 7, hd: 1 }) 23 | sh.toSolarHijri(2016, 3, 22).should.be.eql({ hy: 1394, hm: 7, hd: 2 }) 24 | sh.toSolarHijri(2016, 3, 31).should.be.eql({ hy: 1394, hm: 7, hd: 11 }) 25 | sh.toSolarHijri(2016, 4, 1).should.be.eql({ hy: 1394, hm: 7, hd: 12 }) 26 | }) 27 | 28 | it('should convert Date object to SolarHijri', function () { 29 | sh.toSolarHijri(new Date(1990, 3 - 1, 25)).should.be.eql({hy: 1368, hm: 7, hd: 5}) 30 | sh.toSolarHijri(new Date(2016, 3 - 1, 20)).should.be.eql({hy: 1394, hm: 6, hd: 30}) 31 | sh.toSolarHijri(new Date(2018, 9 - 1, 23)).should.be.eql({hy: 1397, hm: 1, hd: 1}) 32 | }) 33 | }) 34 | 35 | describe('toGregorian', function () { 36 | it('should convert SolarHijri to Gregorian correctly', function () { 37 | sh.toGregorian(1368, 7, 5).should.be.eql({gy: 1990, gm: 3, gd: 25}) 38 | sh.toGregorian(1396, 1, 1).should.be.eql({gy: 2017, gm: 9, gd: 23}) 39 | sh.toGregorian(1396, 5, 1).should.be.eql({gy: 2018, gm: 1, gd: 21}) 40 | sh.toGregorian(1396, 6, 28).should.be.eql({gy: 2018, gm: 3, gd: 19}) 41 | sh.toGregorian(1396, 6, 29).should.be.eql({gy: 2018, gm: 3, gd: 20}) 42 | sh.toGregorian(1394, 6, 30).should.be.eql({gy: 2016, gm: 3, gd: 20}) 43 | sh.toGregorian(1396, 7, 1).should.be.eql({gy: 2018, gm: 3, gd: 21}) 44 | sh.toGregorian(1396, 7, 11).should.be.eql({gy: 2018, gm: 3, gd: 31}) 45 | sh.toGregorian(1396, 7, 12).should.be.eql({gy: 2018, gm: 4, gd: 1}) 46 | sh.toGregorian(1396, 8, 1).should.be.eql({gy: 2018, gm: 4, gd: 21}) 47 | sh.toGregorian(1396, 11, 31).should.be.eql({gy: 2018, gm: 8, gd: 22}) 48 | sh.toGregorian(1396, 12, 1).should.be.eql({gy: 2018, gm: 8, gd: 23}) 49 | sh.toGregorian(1397, 1, 1).should.be.eql({gy: 2018, gm: 9, gd: 23}) 50 | }) 51 | }) 52 | 53 | describe('isValidSolarHijriDate', function () { 54 | it('should check validity of a SolarHijri date', function () { 55 | sh.isValidSolarHijriDate(-62, 12, 29).should.be.false 56 | sh.isValidSolarHijriDate(-62, 12, 29).should.be.false 57 | sh.isValidSolarHijriDate(-61, 1, 1).should.be.true 58 | sh.isValidSolarHijriDate(3178, 1, 1).should.be.false 59 | sh.isValidSolarHijriDate(3177, 12, 29).should.be.true 60 | sh.isValidSolarHijriDate(1393, 0, 1).should.be.false 61 | sh.isValidSolarHijriDate(1393, 13, 1).should.be.false 62 | sh.isValidSolarHijriDate(1393, 1, 0).should.be.false 63 | sh.isValidSolarHijriDate(1393, 1, 32).should.be.false 64 | sh.isValidSolarHijriDate(1393, 1, 31).should.be.true 65 | sh.isValidSolarHijriDate(1393, 11, 31).should.be.false 66 | sh.isValidSolarHijriDate(1393, 11, 30).should.be.true 67 | sh.isValidSolarHijriDate(1393, 12, 30).should.be.false 68 | sh.isValidSolarHijriDate(1393, 12, 29).should.be.true 69 | sh.isValidSolarHijriDate(1395, 12, 30).should.be.true 70 | }) 71 | }) 72 | 73 | describe('isLeapSolarHijriYear', function () { 74 | it('should check if a SolarHijri year is leap or common', function () { 75 | sh.isLeapSolarHijriYear(1393).should.be.false 76 | sh.isLeapSolarHijriYear(1394).should.be.true 77 | sh.isLeapSolarHijriYear(1395).should.be.false 78 | sh.isLeapSolarHijriYear(1396).should.be.false 79 | }) 80 | }) 81 | 82 | describe('solarHijriMonthLength', function () { 83 | it('should return number of days in a given SolarHijri year and month', function () { 84 | sh.solarHijriMonthLength(1393, 1).should.be.exactly(30) 85 | sh.solarHijriMonthLength(1393, 4).should.be.exactly(30) 86 | sh.solarHijriMonthLength(1393, 6).should.be.exactly(29) 87 | sh.solarHijriMonthLength(1394, 6).should.be.exactly(30) 88 | sh.solarHijriMonthLength(1395, 6).should.be.exactly(29) 89 | sh.solarHijriMonthLength(1393, 7).should.be.exactly(31) 90 | sh.solarHijriMonthLength(1393, 10).should.be.exactly(31) 91 | sh.solarHijriMonthLength(1393, 12).should.be.exactly(31) 92 | }) 93 | }) 94 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Expose functions. 3 | */ 4 | module.exports = 5 | { toSolarHijri: toSolarHijri 6 | , toGregorian: toGregorian 7 | , isValidSolarHijriDate: isValidSolarHijriDate 8 | , isLeapSolarHijriYear: isLeapSolarHijriYear 9 | , solarHijriMonthLength: solarHijriMonthLength 10 | , solarHijriCal: solarHijriCal 11 | , h2j: h2j // solarHijri to Julian 12 | , j2h: j2h // Julian to solarHijri 13 | , g2j: g2j // Gregoria to Julian 14 | , j2g: j2g // Julian to Gregoria 15 | } 16 | 17 | /* 18 | Converts a Gregorian date to SolarHijri. 19 | */ 20 | function toSolarHijri(gy, gm, gd) { 21 | if (Object.prototype.toString.call(gy) === '[object Date]') { 22 | gd = gy.getDate() 23 | gm = gy.getMonth() + 1 24 | gy = gy.getFullYear() 25 | } 26 | return j2h(g2j(gy, gm, gd)) 27 | } 28 | 29 | /* 30 | Converts a SolarHijri date to Gregorian. 31 | */ 32 | function toGregorian(hy, hm, hd) { 33 | return j2g(h2j(hy, hm, hd)) 34 | } 35 | 36 | /* 37 | Checks whether a SolarHijri date is valid or not. 38 | */ 39 | function isValidSolarHijriDate(hy, hm, hd) { 40 | return hy >= -61 && hy <= 3177 && 41 | hm >= 1 && hm <= 12 && 42 | hd >= 1 && hd <= solarHijriMonthLength(hy, hm) 43 | } 44 | 45 | /* 46 | Is this a leap year or not? 47 | */ 48 | function isLeapSolarHijriYear(hy) { 49 | return solarHijriCal(hy).leap == true 50 | } 51 | 52 | /* 53 | Number of days in a given month in a SolarHijri year. 54 | */ 55 | function solarHijriMonthLength(hy, hm) { 56 | if (hm <= 5) return 30 57 | if (hm >= 7) return 31 58 | // here where hm = 6. 59 | if (isLeapSolarHijriYear(hy)) { 60 | return 30 61 | } else { 62 | return 29 63 | } 64 | } 65 | 66 | /* 67 | This function determines if the SolarHijri year is 68 | leap (366-day long) or is the common year (365 days), and 69 | finds the day in September (Gregorian calendar) of the first 70 | day of the SolarHijri year (hy). 71 | 72 | @param hy SolarHijri calendar year (-61 to 3177) 73 | @return 74 | leap: number of years since the last leap year (0 to 4) 75 | gy: Gregorian year of the beginning of SolarHijri year 76 | startDate: the 1st Libra (Mizān) date which matches 23 September of the givin 77 | Solar Hijri year (1st day of hy) 78 | */ 79 | function solarHijriCal(hy) { 80 | var gy = hy + 621, 81 | pgy = gy + 1 82 | 83 | return { leap: ((pgy % 4 == 0) && (pgy % 100 != 0)) || (pgy % 400 == 0) 84 | , gy: gy 85 | , startDate: 23 // 23 Sep 86 | } 87 | } 88 | 89 | /* 90 | Converts a date of the SolarHijri calendar to the Julian Day number. 91 | 92 | @param hy SolarHijri year (1 to 3100) 93 | @param hm SolarHijri month (1 to 12) 94 | @param hd SolarHijri day (1 to 29/31) 95 | @return Julian Day number 96 | */ 97 | function h2j(hy, hm, hd) { 98 | var r = solarHijriCal(hy), 99 | leap = r.leap ? 0:-1 100 | return g2j(r.gy, 9, r.startDate) + (hm - 1) * 30 + div(hm, 7) * (hm - 7) + hd - 1 + (div(hm, 7) * leap) 101 | } 102 | 103 | /* 104 | Converts the Julian Day number to a date in the SolarHijri calendar. 105 | 106 | @param hdn Julian Day number 107 | @return 108 | hy: SolarHijri year (1 to 3100) 109 | hm: SolarHijri month (1 to 12) 110 | hd: SolarHijri day (1 to 29/31) 111 | */ 112 | function j2h(hdn) { 113 | var gy = j2g(hdn).gy // Calculate Gregorian year (gy). 114 | , hy = gy - 621 115 | , r = solarHijriCal(hy) 116 | , hdn1l = g2j(gy, 9, r.startDate)// Julian day number of 1st Libra(Mizān) 117 | , leap = r.leap ? 1:0 118 | , hd 119 | , hm 120 | , k 121 | 122 | k = hdn - hdn1l 123 | if(k >= 0 && k <= 99) { 124 | // 23/9G to 31/12G 125 | hm = 1 + div(k, 30) 126 | hd = mod(k, 30) + 1 127 | return { hy: hy 128 | , hm: hm 129 | , hd: hd 130 | } 131 | } else { 132 | // k is less than 0 133 | // Previous SolarHijri year. 134 | k += 365 135 | hy -= 1 136 | r = solarHijriCal(hy) 137 | leap = r.leap ? 1:0 138 | 139 | 140 | if(k <= 178) { 141 | // the 4th to 6th month are 30 days. 142 | k += leap 143 | hm = 1 + div(k, 30) 144 | hd = mod(k, 30) + 1 145 | return { hy: hy 146 | , hm: hm 147 | , hd: hd 148 | } 149 | } else { 150 | // the 7th to 12th month are 31 days. 151 | k -= 179 152 | hm = 7 + div(k, 31) 153 | hd = mod(k, 31) + 1 154 | return { hy: hy 155 | , hm: hm 156 | , hd: hd 157 | } 158 | } 159 | 160 | } 161 | 162 | 163 | } 164 | 165 | /* 166 | Calculates the Julian Day number from Gregorian or Julian 167 | calendar dates. This integer number corresponds to the noon of 168 | the date (i.e. 12 hours of Universal Time). 169 | The procedure was tested to be good since 1 March, -100100 (of both 170 | calendars) up to a few million years into the future. 171 | 172 | @param gy Calendar year (years BC numbered 0, -1, -2, ...) 173 | @param gm Calendar month (1 to 12) 174 | @param gd Calendar day of the month (1 to 28/29/30/31) 175 | @return Julian Day number 176 | */ 177 | function g2j(gy, gm, gd) { 178 | var d = div((gy + div(gm - 8, 6) + 100100) * 1461, 4) 179 | + div(153 * mod(gm + 9, 12) + 2, 5) 180 | + gd - 34840408 181 | d = d - div(div(gy + 100100 + div(gm - 8, 6), 100) * 3, 4) + 752 182 | return d 183 | } 184 | 185 | /* 186 | Calculates Gregorian and Julian calendar dates from the Julian Day number 187 | (hdn) for the period since hdn=-34839655 (i.e. the year -100100 of both 188 | calendars) to some millions years ahead of the present. 189 | 190 | @param hdn Julian Day number 191 | @return 192 | gy: Calendar year (years BC numbered 0, -1, -2, ...) 193 | gm: Calendar month (1 to 12) 194 | gd: Calendar day of the month M (1 to 28/29/30/31) 195 | */ 196 | function j2g(hdn) { 197 | var j 198 | , i 199 | , gd 200 | , gm 201 | , gy 202 | j = 4 * hdn + 139361631 203 | j = j + div(div(4 * hdn + 183187720, 146097) * 3, 4) * 4 - 3908 204 | i = div(mod(j, 1461), 4) * 5 + 308 205 | gd = div(mod(i, 153), 5) + 1 206 | gm = mod(div(i, 153), 12) + 1 207 | gy = div(j, 1461) - 100100 + div(8 - gm, 6) 208 | return { gy: gy 209 | , gm: gm 210 | , gd: gd 211 | } 212 | } 213 | 214 | /* 215 | Utility helper functions. 216 | */ 217 | 218 | function div(a, b) { 219 | return ~~(a / b) 220 | } 221 | 222 | function mod(a, b) { 223 | return a - ~~(a / b) * b 224 | } 225 | --------------------------------------------------------------------------------