/**
 * @name CeL function for astronomical calculations.
 * @fileoverview 本檔案包含了天文演算用的日期轉換功能。
 * 
 * @since 2015/3/20 23:5:43
 * 
 * TODO:
 * 
 * 1. 座標全改 radians
 * 
 * 2. 黃→視黃→赤→(視)赤→地平座標
 * 
 * http://eclipse.gsfc.nasa.gov/JSEX/JSEX-index.html
 * https://web.archive.org/web/http://www.chris.obyrne.com/Eclipses/calculator.html
 * https://en.wikipedia.org/wiki/Astronomical_symbols
 * 
 * calculate Halley's Comet 哈雷彗星
 * 
 * Software & coded<br />
 * http://www.kentauren.info/menu/index1.htm?page=/cgi-bin/planeph_VSOP87d.pl
 * https://pypi.python.org/pypi/astronomia
 * https://github.com/Hedwig1958/libastro/blob/master/astro.c
 * https://github.com/soniakeys/meeus/blob/master/solar/solar.go
 * https://github.com/hkuno9000/sunmoon/blob/master/acoord.cpp
 * http://www.timeanddate.com/calendar/moonphases.html
 * http://eco.mtk.nao.ac.jp/koyomi/
 * 
 * 大地測量:給定地球表面兩個點的經緯度,計算兩點間之距離<br />
 * 天球上天體/星體距離<br />
 * http://geographiclib.sourceforge.net/scripts/geod-calc.html
 * http://wywu.pixnet.net/blog/post/27459116
 * http://iotresearch.wikispaces.com/GPS<br />
 * Andoyer 方法最大的誤差約為50公尺，Lambert 方法最大的誤差約30m。
 * http://usenrong.iteye.com/blog/2147341
 * http://en.wikipedia.org/wiki/Haversine_formula
 * http://en.wikipedia.org/wiki/Spherical_law_of_cosines
 * http://en.wikipedia.org/wiki/Vincenty's_formulae
 * 
 * LUNAR SOLUTION ELP version ELP/MPP02
 * 
 * 未來發展：<br />
 * 
 * @see <a href="http://www.nongli.com/item2/index.html" accessdate="2013/5/2
 *      20:23">农历知识:传统节日,24节气，农历历法，三九，三伏，天文历法,天干地支阴阳五行</a>
 * @see <a href="http://www.chinesefortunecalendar.com/CLC/clcBig5.htm"
 *      accessdate="2013/5/2 20:23">如何轉換陰陽曆</a>
 * 
 * 簡易朔望/天象計算功能/千年 節氣 計算。<br />
 * http://bieyu.com/<br />
 * http://www.fjptsz.com/xxjs/xjw/rj/117/index.htm
 * 
 * 通用万年历 寿星万年历 择吉老黄历 http://www.todayonhistory.com/wnl/lhl.htm
 * 
 */

'use strict';
// 'use asm';

// More examples: see /_test suite/test.js

// ------------------------------------------------------------------------------------------------------------------//

// 不採用 if 陳述式，可以避免 Eclipse JSDoc 與 format 多縮排一層。
typeof CeL === 'function' && CeL.run({
	// module name
	name : 'application.astronomy',

	require : 'data.code.compatibility.'
	// data.math.find_root()
	// data.date.Date_to_JD()
	+ '|data.math.polynomial_value|data.date.',

	// 為了方便格式化程式碼，因此將 module 函式主體另外抽出。
	code : module_code
});

function module_code(library_namespace) {

	// requiring
	var polynomial_value = this.r('polynomial_value');

	/**
	 * full module name.
	 * 
	 * @type {String}
	 */
	var module_name = this.id;

	/**
	 * null module constructor
	 * 
	 * @class astronomical calculations 的 functions
	 */
	var _// JSDT:_module_
	= function() {
		// null module constructor
	};

	/**
	 * for JSDT: 有 prototype 才會將之當作 Class
	 */
	_// JSDT:_module_
	.prototype = {};

	// ------------------------------------------------------------------------------------------------------//
	// basic constants. 定義基本常數。

	var

	/** {Number}未發現之index。 const: 基本上與程式碼設計合一，僅表示名義，不可更改。(=== -1) */
	NOT_FOUND = ''.indexOf('_'),

	/**
	 * 周角 = 360°, 1 turn, 1 revolution, 1 perigon, full circle, complete
	 * rotation, a full rotation in degrees.
	 * 
	 * @type {Number}
	 */
	TURN_TO_DEGREES = 360 | 0,
	/**
	 * 周角.
	 * 
	 * TURN_TO_RADIANS = 2πr/r = 2π =
	 * 6.283185307179586476925286766559005768394338798750211641949889...
	 * 
	 * @type {Number}
	 * 
	 * @see https://en.wikipedia.org/wiki/Radian
	 */
	TURN_TO_RADIANS = 2 * Math.PI,
	/**
	 * degrees * DEGREES_TO_RADIANS = radians.
	 * 
	 * DEGREES_TO_RADIANS = 2π/360 =
	 * 0.017453292519943295769236907684886127134428718885417254560971... ≈
	 * 1.745329251994329576923691e-2
	 * 
	 * @type {Number}
	 */
	DEGREES_TO_RADIANS = TURN_TO_RADIANS / TURN_TO_DEGREES,
	/**
	 * degrees * DEGREES_TO_ARCSECONDS = arcseconds.
	 * 
	 * DEGREES_TO_ARCSECONDS = 3600
	 * 
	 * @type {Number}
	 */
	DEGREES_TO_ARCSECONDS = 60 * 60 | 0,
	/**
	 * Arcseconds in a full circle. 角秒
	 * 
	 * TURN_TO_ARCSECONDS = 1296000
	 * 
	 * @type {Number}
	 */
	TURN_TO_ARCSECONDS = TURN_TO_DEGREES * DEGREES_TO_ARCSECONDS,
	/**
	 * arcseconds * ARCSECONDS_TO_RADIANS = radians.
	 * 
	 * ARCSECONDS_TO_RADIANS = 2π/360/3600 =
	 * 0.0000048481368110953599358991410235794797595635330237270151558... ≈
	 * 4.848136811095359935899141e-6
	 * 
	 * @type {Number}
	 */
	ARCSECONDS_TO_RADIANS = DEGREES_TO_RADIANS / DEGREES_TO_ARCSECONDS,
	/**
	 * 24: 24 hours @ 1 day
	 */
	ONE_DAY_HOURS = 24,
	/**
	 * Seconds per day. 每一天 86400 秒鐘。
	 * 
	 * @type {Number}
	 */
	ONE_DAY_SECONDS = ONE_DAY_HOURS * 60 * 60 | 0;

	// ---------------------------------------------------------------------//
	// 天文相關定常數。

	var
	/**
	 * 每年 2 分點 + 2 至點。
	 * 
	 * EQUINOX_SOLSTICE_COUNT = 4
	 * 
	 * @type {Number}
	 */
	EQUINOX_SOLSTICE_COUNT = 2 + 2,
	/**
	 * 每分至點 90°。
	 * 
	 * EQUINOX_SOLSTICE_DEGREES = 90
	 * 
	 * @type {Number}
	 */
	EQUINOX_SOLSTICE_DEGREES
	//
	= TURN_TO_DEGREES / EQUINOX_SOLSTICE_COUNT,
	/** {Array}二十四節氣名。每月有一個節氣，一個中氣，分別發生在每月的7日和22日前後。 */
	SOLAR_TERMS_NAME =
	// Chinese name: 中氣,節氣,中氣,節氣,...
	'春分,清明,穀雨,立夏,小滿,芒種,夏至,小暑,大暑,立秋,處暑,白露,秋分,寒露,霜降,立冬,小雪,大雪,冬至,小寒,大寒,立春,雨水,驚蟄'
			.split(','),
	/**
	 * 每年 24節氣。
	 * 
	 * SOLAR_TERMS_COUNT = 24
	 * 
	 * @type {Number}
	 */
	SOLAR_TERMS_COUNT = SOLAR_TERMS_NAME.length,
	/**
	 * 每節氣 15°。
	 * 
	 * DEGREES_BETWEEN_SOLAR_TERMS = 15
	 * 
	 * @type {Number}
	 */
	DEGREES_BETWEEN_SOLAR_TERMS = TURN_TO_DEGREES / SOLAR_TERMS_COUNT,
	// 🌑NEW MOON SYMBOL
	// 🌒WAXING CRESCENT MOON SYMBOL
	// ☽FIRST QUARTER MOON
	// 🌓FIRST QUARTER MOON SYMBOL
	// 🌔WAXING GIBBOUS MOON SYMBOL
	// 🌕FULL MOON SYMBOL
	// 🌖WANING GIBBOUS MOON SYMBOL
	// 🌙CRESCENT MOON
	// ☾LAST QUARTER MOON
	// 🌗LAST QUARTER MOON SYMBOL
	// 🌘WANING CRESCENT MOON SYMBOL
	// 🌚NEW MOON WITH FACE
	/**
	 * 各種月相: 新月、上弦月、滿月、下弦月。
	 */
	LUNAR_PHASE_NAME = [
	// gettext_config:{"id":"new-moon"}
	"朔",
	// gettext_config:{"id":"first-quarter"}
	"上弦",
	// gettext_config:{"id":"full-moon"}
	"望",
	// gettext_config:{"id":"last-quarter"}
	"下弦" ],
	/**
	 * 本地之 time zone / time offset (UTC offset by minutes)。<br />
	 * e.g., UTC+8: 8 * 60 = +480<br />
	 * e.g., UTC-5: -5 * 60
	 * 
	 * @type {Number}
	 */
	default_offset = library_namespace.String_to_Date
	//
	&& library_namespace.String_to_Date.default_offset
			|| -(new Date).getTimezoneOffset() || 0;

	_.SOLAR_TERMS = SOLAR_TERMS_NAME;

	// ---------------------------------------------------------------------//
	// Astronomical constant 天文常數。
	// @see https://en.wikipedia.org/wiki/Astronomical_constant
	// @see https://github.com/kanasimi/IAU-SOFA/blob/master/src/sofam.h
	// @see
	// http://asa.usno.navy.mil/static/files/2015/Astronomical_Constants_2015.txt

	var
	/**
	 * Reference epoch (J2000.0), Julian Date. J2000.0 曆元。
	 * 
	 * DAYS_OF_JULIAN_CENTURY = (365 + 1/4) * 100
	 * 
	 * @type {Number}
	 * 
	 * @see https://en.wikipedia.org/wiki/Epoch_%28astronomy%29#Julian_years_and_J2000
	 */
	J2000_epoch = 2451545.0,
	/**
	 * Days per Julian century. 儒略世紀.
	 * 
	 * DAYS_OF_JULIAN_CENTURY = (365 + 1/4) * 100
	 * 
	 * @type {Number}
	 */
	DAYS_OF_JULIAN_CENTURY = 36525,
	/**
	 * speed of light in vacuum (m/s), c 光速.
	 * 
	 * @type {Number}
	 */
	CELERITAS = 299792458,
	/**
	 * Astronomical unit (meters).<br />
	 * 1 astronomical unit = 149597870700 meters (exactly)
	 * 
	 * Astronomical Almanac 2011:<br />
	 * au = A = 149597870700 ± 3 m
	 * 
	 * @type {Number}
	 */
	AU_TO_METERS = 149597870700,
	/**
	 * Light-time for unit (AU) distance (in days).<br />
	 * AU_LIGHT_TIME = 149597870700/299792458/86400 ≈ 0.005775518331436995
	 * 
	 * @type {Number}
	 */
	AU_LIGHT_TIME = AU_TO_METERS / CELERITAS / ONE_DAY_SECONDS,
	/**
	 * Earth mean radius (meter). 地球平均半徑(公尺)。地球半徑6,357km到6,378km。
	 * 
	 * @type {Number}
	 * 
	 * @see https://en.wikipedia.org/wiki/Earth_radius#Mean_radius
	 */
	TERRA_RADIUS_M = 6371009,
	/**
	 * Equatorial radius of Earth (meter). 地球赤道半徑(公尺)。
	 * 
	 * IERS (2003),<br />
	 * Astronomical Almanac 2011:<br />
	 * a_E = a_e = 6378136.6 ± 0.10 m
	 * 
	 * @type {Number}
	 * 
	 * @see https://en.wikipedia.org/wiki/Earth_ellipsoid#Historical_Earth_ellipsoids
	 */
	TERRA_EQUATORIAL_RADIUS_M = 6378136.6,
	/**
	 * Polar radius of Earth (meter). 地球極半徑(公尺)。
	 * 
	 * IERS (2003):<br />
	 * 
	 * @type {Number}
	 * 
	 * @see https://en.wikipedia.org/wiki/Earth_ellipsoid#Historical_Earth_ellipsoids
	 */
	TERRA_POLAR_RADIUS_M = 6356751.9,
	/**
	 * Earth's flattening = 1 / (Reciprocal of flattening).<br />
	 * 地球偏率 = 1 - 極半徑/赤道半徑
	 * 
	 * IERS (2003): 1 / 298.25642
	 * 
	 * @type {Number}
	 * 
	 * @see https://en.wikipedia.org/wiki/Earth_ellipsoid#Historical_Earth_ellipsoids
	 */
	TERRA_FLATTENING = 1 / 298.25642,
	/**
	 * 月球平均半徑 in meter (公尺)。
	 * 
	 * @type {Number}
	 * 
	 * @see http://en.wikipedia.org/wiki/Moon
	 */
	LUNAR_RADIUS_M = 1737100,
	/**
	 * 地月平均距離 in meter (公尺)。
	 * 
	 * 平均距離 mean distance: 384400 km (公里)<br />
	 * 半長軸 Semi-major axis: 384748 km (公里)<br />
	 * 
	 * @type {Number}
	 * 
	 * @see https://en.wikipedia.org/wiki/Lunar_distance_%28astronomy%29
	 * @see http://en.wikipedia.org/wiki/Orbit_of_the_Moon
	 * @see http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
	 */
	LUNAR_DISTANCE_M = 384400000,
	/**
	 * Geocentric semi-diameter of the Sun (in radians) 日面的平均地心視半徑。
	 * 960″.12±0″.09 (696, 342±65km).
	 * 
	 * old: 959.63 arcseconds.<br />
	 * 0°16′ should be added for the semidiameter.<br />
	 * average apparent radius of the Sun (16 arcminutes)
	 * 
	 * @type {Number}
	 * 
	 * @see http://arxiv.org/pdf/1203.4898v1.pdf
	 * @see http://arxiv.org/pdf/1106.2537.pdf
	 * @see http://aa.usno.navy.mil/faq/docs/RST_defs.php
	 * @see https://en.wikipedia.org/wiki/Solar_radius
	 */
	SOLAR_RADIUS_ARCSECONDS = 960.12,
	//
	SOLAR_RADIUS_RADIANS = SOLAR_RADIUS_ARCSECONDS * ARCSECONDS_TO_RADIANS,
	/**
	 * Geocentric semi-diameter of the Sun (in m) 日面的平均地心視半徑。
	 * 
	 * Math.atan(696342000 / 149597870700) / (2 * Math.PI) * 360 * 60 ≈ 16′
	 * 
	 * @type {Number}
	 */
	SOLAR_RADIUS_M = 696342000,
	/**
	 * Constant of aberration (arcseconds). κ 光行差常數
	 * 
	 * 天文學中定義周年光行差常數（簡稱光行差常數）為κ=v/c，其中c是光速，v是地球繞太陽公轉的平均速度
	 * 
	 * Astronomical Almanac 2011:<br />
	 * Constant of aberration at epoch J2000.0:<br />
	 * kappa = 20.49551″
	 * 
	 * @type {Number}
	 * 
	 * @see https://zh.wikipedia.org/wiki/%E5%85%89%E8%A1%8C%E5%B7%AE
	 */
	ABERRATION_κ = 20.49551;

	// ---------------------------------------------------------------------//
	// 初始調整並規範基本常數。

	// ---------------------------------------------------------------------//
	// private tool functions. 工具函數

	/**
	 * 經緯度 pattern [ , °, ′, ″, ″., NEWS ]
	 * 
	 * @type {RegExp}
	 */
	var LATITUDE_PATTERN, LONGITUDE_PATTERN;
	(function() {
		/**
		 * 經緯度 pattern [ , °, ′, ″, ″., NEWS ]
		 * <q>/([+-]?\d+(?:\.\d+)?)°\s*(?:(\d+)[′']\s*(?:(\d+(?:\.\d+)?)(?:″|"|'')(\.\d+)?\s*)?)?([NEWS])/i</q>
		 */
		var d = /([+-]?\d+(?:\.\d+)?)°\s*/, ms =
		//
		/(?:(\d+)[′']\s*(?:(\d+(?:\.\d+)?)(?:″|"|'')(\.\d+)?\s*)?)?/;

		LATITUDE_PATTERN = new RegExp(d.source + ms.source + '([NS])', 'i');
		LONGITUDE_PATTERN = new RegExp(d.source + ms.source + '([EW])', 'i');
	})();

	// 經緯度
	// [ {Number}latitude 緯度, {Number}longitude 經度 ]
	function parse_coordinates(coordinates) {
		var latitude, longitude,
		// e.g., '25.032969, 121.565418'
		matched = coordinates.match(
		//		
		/([+-]?\d+(?:\.\d+)?)(?:\s+|\s*,\s*)([+-]?\d+(?:\.\d+)?)/);
		if (matched)
			return [ +matched[1], +matched[2] ];

		// e.g., 25° 1′ 58.6884″ N 121° 33′ 55.5048″ E
		// e.g., 25° 1' 58.6884'' N 121° 33' 55.5048'' E
		matched = coordinates.match(LATITUDE_PATTERN);
		if (matched) {
			latitude = +matched[1] + (matched[2] ? matched[2] / 60 : 0)
					+ (matched[3] ? matched[3] / 60 / 60 : 0)
					+ (matched[4] ? matched[4] / 60 / 60 : 0);
			if (matched[5].toUpperCase() === 'S')
				latitude = -latitude;
		}
		matched = coordinates.match(LONGITUDE_PATTERN);
		if (matched) {
			longitude = +matched[1] + (matched[2] ? matched[2] / 60 : 0)
					+ (matched[3] ? matched[3] / 60 / 60 : 0)
					+ (matched[4] ? matched[4] / 60 / 60 : 0);
			if (matched[5].toUpperCase() === 'W')
				longitude = -longitude;
		}
		if (latitude || longitude)
			return [ latitude, longitude ];
	}

	_.parse_coordinates = parse_coordinates;

	/**
	 * get Julian centuries since J2000.0.<br />
	 * J2000.0 起算的儒略世紀數.<br />
	 * Interval between fundamental date J2000.0 and given date.
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @returns {Number} Julian centuries of JD from J2000.0
	 */
	function Julian_century(TT_JD) {
		return (TT_JD - J2000_epoch) / DAYS_OF_JULIAN_CENTURY;
	}

	_.Julian_century = Julian_century;

	// normalize degrees
	// to proper degrees 0–less than 360
	// near_0: −180–less than 180
	function normalize_degrees(degrees, near_0) {
		if (!degrees)
			return degrees;
		if ((degrees %= TURN_TO_DEGREES) < 0)
			degrees += TURN_TO_DEGREES;
		if (near_0 && degrees >= TURN_TO_DEGREES / 2)
			degrees -= TURN_TO_DEGREES;
		return degrees;
	}

	_.normalize_degrees = normalize_degrees;

	function normalize_radians(radians, near_0) {
		if (!radians)
			return radians;
		radians = radians.mod(TURN_TO_RADIANS);
		if (near_0 && radians >= TURN_TO_RADIANS / 2)
			radians -= TURN_TO_RADIANS;
		return radians;
	}

	_.normalize_radians = normalize_radians;

	/**
	 * 將時分秒轉成 radians。
	 * 
	 * @param {Number}hours
	 * @param {Number}minutes
	 * @param {Number}seconds
	 * @param {Boolean}to_days
	 *            轉成 days (turns)。
	 * @param {Boolean}is_degrees
	 *            輸入的是 degrees
	 * 
	 * @returns {Number}radians
	 */
	function time_to_radians(hours, minutes, seconds, to_days, is_degrees) {
		if (seconds)
			minutes = (minutes || 0) + seconds / 60;
		hours = ((hours || 0) + (minutes ? minutes / 60 : 0))
		// to days
		/ (is_degrees ? TURN_TO_DEGREES : ONE_DAY_HOURS);
		if (!to_days)
			hours *= TURN_TO_RADIANS;
		return hours;
	}

	_.time_to_radians = time_to_radians;

	/**
	 * 將 degrees 轉成 radians。
	 * 
	 * @param {Number}degrees
	 *            degrees
	 * @param {Number}arcminutes
	 *            arcminutes
	 * @param {Number}arcseconds
	 *            arcseconds
	 * @param {Boolean}to_days
	 *            轉成 days (turns)。
	 * 
	 * @returns {Number}radians
	 */
	function degrees_to_radians(degrees, arcminutes, arcseconds, to_days) {
		if (degrees < 0) {
			if (arcminutes)
				arcminutes = -arcminutes, arcseconds = -arcseconds;
			if (arcseconds)
				arcseconds = -arcseconds;
		}
		return time_to_radians(degrees, arcminutes, arcseconds, to_days, true);
	}

	_.degrees_to_radians = degrees_to_radians;

	/**
	 * 計算角度差距(減法)。 return (base - target), target 會先趨近於 base。或是說結果會向 0 趨近。
	 * 
	 * subtract_degrees(base,target)>0: base>target, base-target>0
	 * 
	 * @param {Object}base
	 *            base coordinates
	 * @param {Object}target
	 *            target coordinates
	 * 
	 * @returns {Number}
	 */
	function subtract_degrees(base, target) {
		if (Math.abs(base = (base - target) % TURN_TO_DEGREES)
		//
		>= TURN_TO_DEGREES / 2)
			if (base > 0)
				base -= TURN_TO_DEGREES;
			else
				base += TURN_TO_DEGREES;
		return base;
	}

	/**
	 * show degrees / sexagesimal system. 顯示易懂角度。
	 * 
	 * @param {Number}degrees
	 *            degrees
	 * @param {Integer}padding
	 *            小數要取的位數。
	 * 
	 * @returns {String}易懂角度。
	 * 
	 * @see https://en.wikipedia.org/wiki/Minute_and_second_of_arc
	 */
	function format_degrees(degree, padding) {
		if (!degree)
			return '0°';

		// is negative.
		var minus = degree < 0;
		// 處理負數。
		if (minus)
			degree = -degree;

		var value = Math.floor(degree),
		//
		show = '';
		if (value > 0) {
			degree -= value;
			// 限制範圍在0至360度內。
			value %= TURN_TO_DEGREES;
			if (padding >= 0 && value < 100)
				show = value > 9 ? ' ' : '  ';
			show += value + '° ';
		}

		if (degree > 0) {
			value = (degree *= 60) | 0;
			if (value || show)
				show += (padding && value < 10 ? ' ' : '')
				//
				+ value + '′ ';
			if (degree -= value) {
				degree *= 60;
				degree = padding >= 0 ? (degree < 10 ? ' ' : '')
						+ degree.toFixed(padding) : String(degree);
				show += degree.includes('.') ? degree.replace('.', '″.')
				// arcseconds
				: degree + '″';
			}
		}

		// 處理負數。
		if (minus)
			show = '-' + show;

		return show.replace(/ $/, '');
	}

	_.format_degrees = format_degrees;

	/**
	 * show time angle. 顯示易懂時角。
	 * 
	 * @param {Number}days
	 *            days / turns
	 * 
	 * @returns {String}易懂時角。
	 * 
	 * @see https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts
	 */
	function days_to_time(days) {
		var show = '', minus = days < 0;
		// 處理負數。
		if (minus)
			days = -days;

		// time: hours
		var time = (days % 1) * ONE_DAY_HOURS;
		if (days |= 0)
			show += days + 'ᵈ';

		days = time | 0;
		if (days || show)
			show += days + 'ʰ';

		// time: minutes
		time = (time % 1) * 60;
		days = time | 0;
		if (days || show)
			show += days + 'ᵐ';

		// time: seconds
		time = (time % 1) * 60;
		if (days || show)
			show += days + 'ˢ';
		// time <= 1e-10: 當作 error。
		// 1e-11: -Math.log10((1/2-1/3-1/6)*86400)|0
		if ((time %= 1) > 1e-11) {
			// 去首尾之 0。
			time = time.toPrecision(11).replace(/0+$/, '').replace(/^0+/, '');
			if (show)
				show += time;
			else
				show = '0ˢ' + time;
		} else if (!show) {
			show = '0';
		}

		// 收尾。

		// 處理負數。
		if (minus)
			show = '-' + show;

		return show;
	}

	_.days_to_time = days_to_time;

	/**
	 * format radians
	 * 
	 * @param {Number}radians
	 *            radians to format
	 * @param {String}[to_type]
	 *            to what type: decimal degrees, degrees, time, radians, turns
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 * 
	 * @returns {String}formatted radians
	 */
	function format_radians(radians, to_type, options) {
		if (!to_type)
			// default: degrees of sexagesimal measure
			to_type = 'degrees';

		switch (to_type) {
		case 'decimal':
		case 'decimal degrees':
			return radians / DEGREES_TO_RADIANS;
		case 'degrees':
			return format_degrees(radians / DEGREES_TO_RADIANS, options
					&& options.padding);
		case 'turns':
			return radians / TURN_TO_RADIANS;
		case 'time':
			return days_to_time(radians / TURN_TO_RADIANS);
		}
		// default
		return radians;
	}

	_.format_radians = format_radians;

	// ------------------------------------------------------------------------------------------------------//
	// semi-diameter of objects

	/**
	 * 天體的中心視半徑 (in arcseconds)。
	 * 
	 * e.g., Geocentric semi-diameter of the Sun, apparent radius, 日面的地心視半徑。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 390. Chapter 55 Semidiameters of the Sun, Moon, and Planets
	 * 
	 * @param {Object|Number}coordinates
	 *            coordinates or distance (in AU) of object
	 * @param {Number|String}[radius]
	 *            object radius (in arcseconds) or object name. default: sun
	 * @param {Number}[latitude]
	 *            object-centric latitude of the Earth.<br />
	 *            e.g., Saturnicentric latitude of the Earth (see Chapter 45).<br />
	 *            “以土星為中心”的緯度(詳見《天文算法》第45章)。
	 * 
	 * @returns {Number}semi-diameter (in arcseconds)
	 * 
	 * @see https://github.com/soniakeys/meeus/blob/master/semidiameter/semidiameter.go
	 */
	function semidiameter(coordinates, radius, latitude) {
		var object = coordinates && coordinates.object
				|| (isNaN(radius) ? radius : SUN_NAME);
		if (!radius)
			radius = object;
		if (radius in semidiameter.apparent)
			radius = semidiameter.apparent[object = radius];
		else if (radius === SUN_NAME)
			object = radius, radius = SOLAR_RADIUS_ARCSECONDS;
		// assert: radius is in arcseconds now.

		var distance = typeof coordinates === 'number' && coordinates > 0 ? coordinates
				: coordinates.Δ
						|| (object === MOON_NAME ? LUNAR_DISTANCE_M
								/ AU_TO_METERS
						// 1: default: 1 AU
						: 1);
		// assert: distance is in AU now.

		if (object === MOON_NAME) {
			if (false && coordinates.Δ > 0) {
				radius = Math.atan(LUNAR_RADIUS_M / AU_TO_METERS
						/ coordinates.Δ)
						/ ARCSECONDS_TO_RADIANS;
				if (latitude)
					// → 以觀測者為中心的座標中看到的月亮視半徑
					radius += radius * Math.sin(latitude * DEGREES_TO_RADIANS)
							* TERRA_RADIUS_M / LUNAR_DISTANCE_M;
				return radius;
			}

			// 設Δ是地球中心到月球中心到的距離(單位是千米)，
			distance *= AU_TO_METERS / 1000;
			/**
			 * π是月球的赤道地平視差，s是月亮的地心視半徑，k是月亮平均半徑與地球赤道半徑的比值。在1963到1968年的天文曆書中，日月食計算中取k=0.272481
			 * 
			 * Explanatory Supplement to the Astronomical Ephemeris. Third
			 * impression 1974.<br />
			 * p. 213.<br />
			 * As from 1963, the value of k is taken as 0.2724807, which leads
			 * to the same value of the semi-diameter as in the lunar ephemeris.
			 * The value 0.272274 for k is retained, however, in the calculation
			 * of duration on the central line of total solar eclipses, by way
			 * of applying an approximate correction for the irregularities of
			 * the lunar limb.
			 * 
			 * Explanatory Supplement to the Astronomical Almanac.<br />
			 * p. 425.<br />
			 * The lAU adopted a new value of k (k = 0.2725076) in August 1982.
			 */
			var k = 0.272481, sin_π = 6378.14 / distance;
			if (coordinates && coordinates.LHA) {
				// p. 280. formula 40.7
				var A = Math.cos(coordinates.δ) * Math.sin(coordinates.LHA),
				//
				B = Math.cos(coordinates.δ) * Math.cos(coordinates.LHA)
						- coordinates.ρcos_φp * sin_π,
				//
				C = Math.sin(coordinates.δ) - coordinates.ρsin_φp * sin_π;
				/**
				 * the topocentric distance of the Moon (that is, the distance
				 * from the observer to the center of the Moon) is Δ′=q*Δ, q
				 * being given by formula (40.7).
				 */
				distance *= Math.sqrt(A * A + B * B + C + C);
				sin_π = 6378.14 / distance;
			}
			radius = Math.asin(k * sin_π) / ARCSECONDS_TO_RADIANS;
		} else {
			radius /= distance;

			if (latitude && object
					&& ((object + '_polar') in semidiameter.apparent)) {
				// 極半徑/赤道半徑
				var k = semidiameter.apparent[object + '_polar']
						/ semidiameter.apparent[object];
				k = 1 - k * k;
				latitude = Math.cos(latitude * DEGREES_TO_RADIANS);
				radius *= Math.sqrt(1 - k * latitude * latitude);
			}
		}

		return radius;
	}

	_.semidiameter = semidiameter;

	/**
	 * apparent radius (arcseconds). 距離 1 AU 時的太陽和行星的視半徑。
	 * 
	 * @type {Object}
	 */
	semidiameter.apparent = {
		mercury : 3.36,
		venus_surface : 8.34,
		// +cloud
		// 對於金星，值8″.34，指從地球上看它的地殼半徑，而不是指它的雲層。由於這個原因，當計算諸如中天、淩日、星食等天文現象時，我們採用舊值8″.41。
		venus : 8.41,
		mars : 4.68,
		// equatorial
		jupiter : 98.44,
		jupiter_polar : 92.06,
		// equatorial
		saturn : 82.73,
		saturn_polar : 73.82,
		uranus : 35.02,
		neptune : 33.50,
		pluto : 2.07
	};

	// ------------------------------------------------------------------------------------------------------//
	// coordinate transformations 座標變換
	// @see
	// https://en.wikipedia.org/wiki/List_of_common_coordinate_transformations

	/**
	 * auto detect time zone. 自動判別時區。
	 * 
	 * @param {Array}local
	 *            the observer's geographic location [ latitude (°), longitude
	 *            (°), time zone (e.g., UTC+8: 8), elevation or geometric height
	 *            (m) ]<br />
	 *            觀測者 [ 緯度（北半球為正,南半球為負）, 經度（從Greenwich向東為正，西為負）, 時區,
	 *            海拔標高(觀測者距海平面的高度) ]
	 * 
	 * @returns {Number}time zone. UTC+8: 8
	 */
	function get_time_zone(local) {
		return isNaN(local[2]) ? Math.round(local[1]
				/ (TURN_TO_DEGREES / ONE_DAY_HOURS)) : local[2];
	}

	/**
	 * 此函數為為了舊曆元所做的修正。
	 * 
	 * longitude λ must be converted to the ephemeris longitude λ* by increasing
	 * it by 1.002738 ΔT, the sidereal equivalent of ΔT.
	 * 
	 * 星曆用的經度從Greenwich向西為正，東為負，與向東為正的一般地理經度用法相反。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Explanatory Supplement to the Astronomical Ephemeris. Third impression
	 * 1974.<br />
	 * p. 241.
	 * 
	 * The ephemeris meridian is 1.002 738 ΔT east of the Greenwich meridian,
	 * where ΔT=TT−UT1.
	 * 
	 * @param {Number}longitude
	 *            longitude of geographic coordinate in degrees, 一般地理經度
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @returns {Number}ephemeris longitude in radians, 星曆用的經度
	 * 
	 * @see http://asa.usno.navy.mil/SecM/Glossary.html
	 */
	function to_ephemeris_longitude(longitude, TT_JD) {
		return -longitude * DEGREES_TO_RADIANS;

		return ((TT_JD ? 1.002738 * ΔT_of_JD(TT_JD) : 0) - longitude)
				* DEGREES_TO_RADIANS;
	}

	/**
	 * ephemeris longitude → geographic longitude
	 * 
	 * @param {Number}longitude
	 *            ephemeris longitude in radians, 星曆用的經度
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @returns {Number}geographic longitude in degrees
	 */
	function from_ephemeris_longitude(longitude, TT_JD) {
		return normalize_radians(-longitude, true) /
		//
		DEGREES_TO_RADIANS;

		return (TT_JD ? -1.002738 * ΔT_of_JD(TT_JD) : 0) - longitude
				/ DEGREES_TO_RADIANS;
	}

	/**
	 * 計算角距離 angular distance (in radians)
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 109. formula 17.1
	 * 
	 * @param {Object}coordinates_1
	 *            apparent geocentric ecliptical coordinates<br /> { longitude
	 *            α , latitude δ } in radians
	 * @param {Object}coordinates_2
	 *            apparent geocentric ecliptical coordinates<br /> { longitude
	 *            α , latitude δ } in radians
	 * 
	 * @returns {Number}angular distance in radians
	 */
	function angular_distance(coordinates_1, coordinates_2, no_minor_squre) {
		var Δα = Math.abs(coordinates_1.α - coordinates_2.α), Δδ,
		//
		δ1 = coordinates_1.δ, δ2 = coordinates_2.δ;
		// 10 / 60 / 360 * (2 * Math.PI) = 0.0029088820866572155
		if (!no_minor_squre && Δα < .001 && (Δδ = Math.abs(δ1 - δ2)) < .001) {
			// 角度差接近於0或180度時，求取近似值。
			Δα *= Math.cos((δ1 + δ2) / 2);
			return Math.sqrt(Δα * Δα + Δδ * Δδ);
		}
		if (false)
			console.log(Math.sin(δ1) * Math.sin(δ2) + Math.cos(δ1)
					* Math.cos(δ2) * Math.cos(Δα));
		return Math.acos(Math.sin(δ1) * Math.sin(δ2) + Math.cos(δ1)
				* Math.cos(δ2) * Math.cos(Δα));
	}

	_.angular_distance = angular_distance;

	/**
	 * 向量長度，與原點距離。
	 * 
	 * @param {Array}rectangular
	 *            直角座標 [ x, y, z ]
	 * 
	 * @returns {Number}distance
	 */
	function distance_of_rectangular(rectangular) {
		var x = rectangular[0], y = rectangular[1], z = rectangular[2];
		return Math.sqrt(x * x + y * y + z * z);
	}

	/**
	 * spherical coordinates → rectangular coordinates. 球座標系(日心座標)轉為直角座標系。
	 * 
	 * @param {Number}longitude
	 *            longitude (L) of spherical 球座標
	 * @param {Number}latitude
	 *            latitude (B) of spherical 球座標
	 * @param {Number}radius
	 *            radius (R) of spherical 球座標
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            {Boolean}options.unit_radius: 若為 true，則將 .R 當作 1。<br />
	 *            {Object}options.base: base spherical coordinates. {L,B,R}
	 *            基準球座標.
	 * 
	 * @returns {Object}rectangular coordinates [ x, y, z ]
	 * 
	 * @see https://en.wikipedia.org/wiki/Ecliptic_coordinate_system#Rectangular_coordinates
	 *      https://en.wikipedia.org/wiki/Equatorial_coordinate_system#Geocentric_equatorial_coordinates
	 */
	function spherical_to_rectangular(longitude, latitude, radius, options) {
		if (library_namespace.is_Object(longitude)) {
			options = latitude;
			radius = longitude.R;
			latitude = longitude.B;
			longitude = longitude.L;
		}

		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var tmp, cos_B = Math.cos(latitude),
		//
		x = cos_B * Math.cos(longitude), y = cos_B * Math.sin(longitude), z = Math
				.sin(latitude);

		if (!options.unit_radius && radius) {
			x *= radius;
			y *= radius;
			z *= radius;
		}

		if (tmp = options.base) {
			tmp = spherical_to_rectangular(tmp, options.unit_radius ? {
				unit_radius : true
			} : null);
			x -= tmp[0];
			y -= tmp[1];
			z -= tmp[2];
		}

		tmp = [ x, y, z ];
		if (options.distance)
			tmp.distance = Math.sqrt(x * x + y * y + z * z);

		// return rectangular
		return tmp;
	}

	/**
	 * rectangular coordinates → spherical coordinates. 直角座標系轉為球座標系(黃道座標)。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 223. formula 33.2 座標變換
	 * 
	 * @param {Array}rectangular
	 *            直角座標 [ x, y, z ]
	 * @param {Boolean}get_radius
	 *            亦生成 radius
	 * 
	 * @returns {Object}spherical coordinates { λ , β }
	 */
	function rectangular_to_spherical(rectangular, get_radius) {
		var x = rectangular[0], y = rectangular[1], z = rectangular[2],
		// ecliptical (or celestial) [ longitude 黃經, latitude 黃緯 ]。
		spherical = [ Math.atan2(y, x), Math.atan2(z, Math.sqrt(x * x, y * y)) ];
		if (get_radius)
			spherical.push(Math.sqrt(x * x + y * y + z * z));
		return spherical;
	}

	/**
	 * Transformation from ecliptical into equatorial coordinates. G地心視黃道座標轉到
	 * E地心赤道座標(視赤經及視赤緯)
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 93. formula 13.3, 13.4
	 * 
	 * @param {Object}coordinates
	 *            apparent geocentric ecliptical coordinates<br /> { longitude
	 *            λ , latitude β }
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項
	 * 
	 * @returns {Object}equatorial coordinates { right ascension α , declination
	 *          δ }
	 */
	function ecliptical_to_equatorial(coordinates, TT_JD, options) {
		var ε = obliquity(TT_JD),
		// G地心視黃道 apparent geocentric ecliptic coordinates:
		// longitude λ and latitude β in radians
		λ = coordinates.λ, β = coordinates.β,
		// cache
		sin_λ = Math.sin(λ), cos_ε = Math.cos(ε), sin_ε = Math.sin(ε);

		// geocentric right ascension 地心赤經。
		coordinates.α = Math.atan2(sin_λ * cos_ε - Math.tan(β) * sin_ε, Math
				.cos(λ));
		// geocentric declination 地心赤緯。
		coordinates.δ = Math.asin(Math.sin(β) * cos_ε + Math.cos(β) * sin_ε
				* sin_λ);

		// 因為 equatorial_to_horizontal() 可能會再利用，這裡不處理 options.degrees。
		return coordinates;
	}

	/**
	 * equatorial coordinates → local horizontal coordinates.
	 * 依據觀測者的位置和時間，轉換地心視赤道座標到本地站心地平座標系。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 93. formula 13.5, 13.6 座標變換<br />
	 * Chapter 40: Correction for Parallax
	 * 
	 * @param {Object}coordinates
	 *            equatorial coordinates { right ascension α , declination δ }
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Array}local
	 *            the observer's geographic location [ latitude (°), longitude
	 *            (°), time zone (e.g., UTC+8: 8), elevation or geometric height
	 *            (m) ]<br />
	 *            觀測者 [ 緯度（北半球為正,南半球為負）, 經度（從Greenwich向東為正，西為負）, 時區,
	 *            海拔標高(觀測者距海平面的高度) ]
	 * 
	 * @returns {Object}horizontal { Alt:altitude (radians) , Az:azimuth
	 *          (radians) }
	 * 
	 * @see https://en.wikipedia.org/wiki/Horizontal_coordinate_system
	 */
	function equatorial_to_horizontal(coordinates, TT_JD, local) {
		/**
		 * 地心赤緯δ。
		 * 
		 * @type {Number}
		 */
		var δ = coordinates.δ;
		if (isNaN(δ))
			// 先算出地心視赤道座標。
			// 一般已在 function get_horizontal() 中處理。
			δ = ecliptical_to_equatorial(coordinates, TT_JD).δ;

		/**
		 * 地心赤經α。
		 * 
		 * @type {Number}
		 */
		var α = coordinates.α,
		/**
		 * Phi: lower-case letter φ (or often its variant, ϕ) 觀測者緯度（北半球為正,南半球為負）
		 * 
		 * @type {Number}
		 */
		φ = local[0] * DEGREES_TO_RADIANS,
		// p. 92.
		/**
		 * Greenwich視恆星時θ0
		 * 
		 * @type {Number} in radians
		 */
		θ0 = GAST(TT_of(TT_JD, true), TT_JD),
		/**
		 * 本地恆星時θ = Greenwich視恆星時θ0 - L觀測者星曆經度
		 * 
		 * @type {Number} in radians
		 */
		θ = θ0 - to_ephemeris_longitude(local[1], TT_JD),
		/**
		 * local hour angle (in radians)
		 * 本地地心時角。一個天體的時角是2.5HA，就表示他已經在2.5個小時之前通過當地的子午圈，並且在當地子午圈的西方37.5度的距離上。負數則表示在多少小時之後將通過當地的子午圈。
		 * 
		 * LHA = 本地恆星時θ − 地心赤經α = Greenwich視恆星時θ0 - L觀測者星曆經度 − 地心赤經α
		 * 
		 * @type {Number} in radians
		 */
		LHA = θ - α,
		// cache
		sin_φ = Math.sin(φ), cos_φ = Math.cos(φ),
		// cache
		cos_H = Math.cos(LHA),
		// p. 82.
		// tmp
		u = Math.atan(TERRA_POLAR_RADIUS_M / TERRA_EQUATORIAL_RADIUS_M
				* Math.tan(φ));

		// tmp
		LHA /= TERRA_EQUATORIAL_RADIUS_M;
		/**
		 * 計算周日視差、日月食、星蝕所需要的量ρsin(φ′)
		 * 
		 * @type {Number}
		 */
		var ρsin_φp = TERRA_POLAR_RADIUS_M / TERRA_EQUATORIAL_RADIUS_M
				* Math.sin(u) + LHA * sin_φ,
		/**
		 * 計算周日視差、日月食、星蝕所需要的量ρcos(φ′)
		 * 
		 * @type {Number}
		 */
		ρcos_φp = Math.cos(u) + LHA * cos_φ;

		coordinates.ρsin_φp = ρsin_φp;
		coordinates.ρcos_φp = ρcos_φp;

		// p. 279.
		// 地心視赤道座標轉到本地站心赤道座標:
		// 修正 planet's parallax (行星視差)
		var
		/**
		 * the equatorial horizontal parallax of the body in radians. 天體的赤道地平視差.
		 * 
		 * Math.sin(8.794 * ARCSECONDS_TO_RADIANS) ≈ 0.0000426345
		 * 
		 * @type {Number} in radians
		 */
		π = Math.asin(Math.sin(8.794 * ARCSECONDS_TO_RADIANS)
		// coordinates.Δ: apparent distance at TT_JD in AU in radians
		// 對於太陽、行星和慧星，經常適合使用它們到地球的距離Δ替代視差
		/ coordinates.Δ),
		// cache
		sin_π = Math.sin(π), cos_δ = Math.cos(δ);
		coordinates.π = π;
		// tmp
		u = ρcos_φp * sin_π;
		π = cos_δ - u * cos_H;
		var Δα = Math.atan2(-u * Math.sin(LHA), π);
		// 對於赤緯，不必計算Δδ，用下式可直接算出δ′：
		// apply new value to (δ, α, LHA).
		δ = Math.atan2((Math.sin(δ) - ρsin_φp * sin_π) * Math.cos(Δα), π);
		α += Δα;
		// T站心赤道 topocentric equatorial coordinate system
		// @see function Coordinates()
		coordinates.T = [ α, δ ];

		// coordinates.θ0 = θ0;
		// coordinates.θ = θ;
		// LHA: local hour angle (in radians) 本地地心時角。
		coordinates.LHA = LHA = θ - α;
		// re-cache
		cos_H = Math.cos(LHA);

		// p. 93.
		// 站心赤道座標轉到站心地平座標 (radians)
		// Altitude (Alt) 高度角或仰角又稱地平緯度。
		// 修正大氣折射的影響
		// TODO: 考慮 dip of the horizon (地平俯角, 海岸視高差)
		// @see
		// https://en.wikipedia.org/wiki/Horizon#Effect_of_atmospheric_refraction
		// http://www-rohan.sdsu.edu/~aty/explain/atmos_refr/altitudes.html
		coordinates.Alt = refraction(Math.asin(sin_φ * Math.sin(δ) + cos_φ
				* Math.cos(δ) * cos_H)
				/ DEGREES_TO_RADIANS)
				* DEGREES_TO_RADIANS;
		// Azimuth (Az) 方位角又稱地平經度。
		coordinates.Az = Math.atan2(Math.sin(LHA), cos_H * sin_φ - Math.tan(δ)
				* cos_φ);

		// parallactic angle
		// https://en.wikipedia.org/wiki/Parallactic_angle
		// Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版
		// p. 98. formula 14.1
		if (false
		// 當天體正好在天頂，則沒有定義。
		&& (π = Math.tan(φ) * Math.cos(δ) - Math.sin(δ) * cos_H))
			coordinates.parallactic = Math.atan2(Math.sin(LHA), π);

		// 因為可能會再利用，這裡不處理 options.degrees。
		return coordinates;
	}

	/**
	 * ecliptical → equatorial coordinates → local horizontal coordinates.
	 * 
	 * @param {Object}coordinates
	 *            apparent geocentric ecliptical coordinates<br /> { longitude
	 *            λ , latitude β }
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項
	 */
	function get_horizontal(coordinates, TT_JD, options) {
		var local = Array.isArray(options.local) && options.local;
		if (local || options.equatorial) {
			// 地心視黃道座標轉到視赤道座標(視赤經及視赤緯)。
			ecliptical_to_equatorial(coordinates, TT_JD, options);
			// 需要保證有 coordinates.Δ
			if (local && coordinates.Δ)
				equatorial_to_horizontal(coordinates, TT_JD, local);
			// 單位轉換。
			if (options.degrees) {
				if (local) {
					coordinates.Alt /= DEGREES_TO_RADIANS;
					coordinates.Az /= DEGREES_TO_RADIANS;
				}
				coordinates.α /= DEGREES_TO_RADIANS;
				coordinates.δ /= DEGREES_TO_RADIANS;
			}
		}

		// elongation Ψ of the planet, its angular distance to the Sun
		// https://en.wikipedia.org/wiki/Elongation_%28astronomy%29
		// 行星的距角，即地心看行星與太陽的角距離 (angular distance)。
		// Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版
		// Chapter 48 Illuminated Fraction of the Moon's Disk
		if (options.elongation) {
			// the Sun's apparent longitude in degrees → radians.
			var solar = solar_coordinates(TT_JD, {
				equatorial : true
			}),
			//
			λ0 = solar.apparent * DEGREES_TO_RADIANS,
			//
			cos_Ψ = Math.cos(coordinates.β) * Math.cos(coordinates.λ - λ0);
			// The Sun's latitude, which is always smaller than 1.2
			// arcsecond, may be neglected here.
			// 地心座標下的月球距角ψ
			coordinates.Ψ = Math.acos(cos_Ψ);
			// 月心座標下的地球距角i
			coordinates.i = Math.atan2(solar.Δ * Math.sin(coordinates.Ψ),
					coordinates.Δ - solar.Δ * cos_Ψ);
			// ψ和i在均在0到180度之間。

			// 月亮明亮邊緣的位置角
			coordinates.χ = Math.atan2(Math.cos(solar.δ)
					* Math.sin(solar.α - coordinates.α), Math.sin(solar.δ)
					* Math.cos(coordinates.δ) - Math.cos(solar.δ)
					* Math.sin(coordinates.δ)
					* Math.cos(solar.α - coordinates.α));

			// 單位轉換。
			if (options.degrees) {
				coordinates.Ψ /= DEGREES_TO_RADIANS;
				coordinates.i /= DEGREES_TO_RADIANS;
				coordinates.χ /= DEGREES_TO_RADIANS;
			}
		}
	}

	// ------------------------------------------------------------------------------------------------------//
	// ΔT

	/**
	 * get ΔT of year.<br />
	 * ΔT = TT - UT<br />
	 * <br />
	 * 天文計算/星曆表使用 Terrestrial Time (TT, 地球時標)，<br />
	 * 日常生活中使用 UTC, 接近 Universal Time (UT, 世界時標), 主要為 UT1。<br />
	 * <br />
	 * 簡略的說，天文計算用時間 TT = 日常生活時間 UT + ΔT
	 * 
	 * ΔT is NOT △T
	 * 
	 * @param {Number}year
	 *            the year value of time = year + (month - 0.5) / 12
	 * @param {Number}[month]
	 *            the month of time.
	 * 
	 * @returns {Number} ΔT of year in seconds.
	 * 
	 * @see https://en.wikipedia.org/wiki/%CE%94T
	 * @see <a href="http://www.cv.nrao.edu/~rfisher/Ephemerides/times.html"
	 *      accessdate="2015/3/25 20:35">Astronomical Times</a>
	 * @see http://njsas.org/projects/speed_of_light/roemer/tt-utc.html
	 * 
	 * @since 2015/3/21 9:23:32
	 */
	function ΔT(year, month) {
		if (month > 0)
			year += (month - 0.5) / 12;

		var index = 0;
		while (true) {
			if (year >= ΔT_year_start[index])
				break;
			if (++index === ΔT_year_start.length) {
				// before −500: the same as after 2150.
				index = 0;
				break;
			}
		}

		var deltaT = polynomial_value(ΔT_coefficients[index],
				(year - ΔT_year_base[index]) / 100);
		library_namespace.debug('ΔT of year ' + year + ': ' + deltaT
				+ ' seconds', 3);

		return deltaT;
	}

	_.deltaT = _.ΔT = ΔT;

	/**
	 * get ΔT of JD.<br />
	 * ΔT = TT - UT<br />
	 * <br />
	 * 天文計算/星曆表使用 Terrestrial Time (TT, 地球時標)，<br />
	 * 日常生活中使用 UTC, 接近 Universal Time (UT, 世界時標), 主要為 UT1。<br />
	 * <br />
	 * 簡略的說，天文計算用時間 TT = 日常生活時間 UT + ΔT
	 * 
	 * @param {Number}JD
	 *            Julian date
	 * 
	 * @returns {Number} ΔT of year in seconds.
	 */
	function ΔT_of_JD(JD) {
		// + 2000: Julian_century(JD) starts from year 2000.
		return ΔT(Julian_century(JD) * 100 + 2000);
	}

	_.deltaT.JD = ΔT_of_JD;

	/**
	 * get Terrestrial Time of Universal Time JD, apply ΔT to UT.
	 * 
	 * @param {Number}UT_JD
	 *            Julian date (JD of 日常生活時間 UT)
	 * @param {Boolean}[TT_to_UT]
	 *            reverse, TT → UT. treat JD as 天文計算用時間 TT.
	 * 
	 * @returns {Number}JD of TT
	 */
	function TT_of(UT_JD, TT_to_UT) {
		if (library_namespace.is_Date(UT_JD))
			UT_JD = library_namespace.Date_to_JD(UT_JD);
		var deltaT = ΔT_of_JD(UT_JD) / ONE_DAY_SECONDS;
		// normal: UT → TT.
		// TT_to_UT: TT → UT.
		// 簡略的說，日常生活時間 UT = 天文計算用時間 TT - ΔT
		return TT_to_UT ? UT_JD - deltaT : UT_JD + deltaT;
	}

	/**
	 * Translate Terrestrial Time JD → Universal Time JD.
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @returns {Number}JD of UT
	 */
	function UT_of(TT_JD) {
		return TT_of(TT_JD, true);
	}

	_.TT = TT_of;
	_.UT = UT_of;

	// ------------------------------------------------------------------------------------------------------//
	// Atmospheric refraction 大氣折射又稱蒙氣差、折光差（蒙氣即行星的大氣）

	/**
	 * true apparent in degrees ← apparent altitude.<br />
	 * 大氣折射公式: 真地平緯度 ← 視地平緯度<br />
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * chapter 大氣折射.<br />
	 * based on: G. G. Bennett. (1982). "The Calculation of Astronomical
	 * Refraction in Marine Navigation".
	 * 
	 * @param {Number}apparent
	 *            apparent altitude in degrees. 視地平緯度/高度角或仰角，單位是度。
	 * @param {Number}[Celsius]
	 *            temperature in degree Celsius. 攝氏度氣溫
	 * @param {Number}[pressure]
	 *            pressure in kPa. 地表氣壓
	 * 
	 * @returns {Number} degrees of true apparent. 單位是度
	 * 
	 * @since 2015/3/21 21:31:17
	 * 
	 * @see https://en.wikipedia.org/wiki/Atmospheric_refraction#Calculating_refraction
	 * @see http://www.astro.com/ftp/swisseph/src/swecl.c
	 */
	function refraction_to_real(apparent, Celsius, pressure) {
		// (86.63175) get 4.186767499821572e-10
		// 經測試，再多就變負數。
		if (apparent > 86.63175)
			// Jean Meeus: 在90°時，不作第二項修正反而更好。
			return apparent;

		// refraction in arcminutes. 折射角單位是分。
		var refraction = 1 / Math.tan((apparent + 7.31 / (apparent + 4.4))
				* DEGREES_TO_RADIANS);
		// 第二項公式修正
		refraction -= 0.06 * Math.sin(14.7 * refraction + 13);
		// assert: refraction > 0

		// Jean Meeus: 大約修正。折射率還與光的波長有關。這些運算式適用于黃光，它對人眼的靈敏度最高。
		// @see
		// http://www.iausofa.org/2015_0209_C/sofa/sofa_ast_c.pdf#75
		// 常規條件: Both formulas assume an atmospheric pressure
		// of 101.0 kPa and a temperature of 10 °C
		if (!isNaN(Celsius))
			// [K] = [°C] + 273.15
			refraction *= (273 + 10) / (273 + refraction);
		if (pressure >= 0)
			refraction *= pressure / 101;

		// 1度 = 60分
		return apparent - refraction / 60;
	}

	/**
	 * apparent altitude in degrees ← true altitude.<br />
	 * 大氣折射公式: 視地平緯度 ← 真地平緯度
	 * 
	 * @param {Number}real
	 *            real altitude in degrees. 真地平緯度/高度角或仰角，單位是度。
	 * @param {Number}[Celsius]
	 *            temperature in degree Celsius. 攝氏度氣溫
	 * @param {Number}[pressure]
	 *            pressure in kPa. 地表氣壓
	 * 
	 * @returns {Number} degrees of apparent altitude. 單位是度
	 * 
	 * @since 2015/3/21 21:31:17
	 * 
	 * @see https://en.wikipedia.org/wiki/Atmospheric_refraction#Calculating_refraction
	 * @see http://www.astro.com/ftp/swisseph/src/swecl.c
	 */
	function refraction(real, Celsius, pressure) {
		// (89.891580) get 2.226931796052203e-10
		// 經測試，再多就變負數。
		if (real > 89.89158)
			// Jean Meeus: h=90°時，該式算得R不等於零。
			return real;

		// refraction in arcminutes. 折射角單位是分.
		var refraction = 1.02 / Math.tan((real + 10.3 / (real + 5.11))
				* DEGREES_TO_RADIANS);
		// assert: refraction > 0

		// Jean Meeus: 大約修正。折射率還與光的波長有關。這些運算式適用于黃光，它對人眼的靈敏度最高。
		// 常規條件: Both formulas assume an atmospheric pressure
		// of 101.0 kPa and a temperature of 10 °C
		if (!isNaN(Celsius))
			// [K] = [°C] + 273.15
			refraction *= (273 + 10) / (273 + refraction);
		if (pressure >= 0)
			refraction *= pressure / 101;

		// 1度 = 60分
		return real + refraction / 60;
	}

	refraction.to_real = refraction_to_real;
	_.refraction = refraction;

	// ------------------------------------------------------------------------------------------------------//
	// obliquity 轉軸傾角。

	/**
	 * 地球的平均轉軸傾角，平黃赤交角。 get mean obliquity of the ecliptic (Earth's axial tilt),
	 * IAU 2006 precession model.
	 * 
	 * Reference 資料來源/資料依據:
	 * https://github.com/kanasimi/IAU-SOFA/blob/master/src/obl06.c
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @returns {Number} obliquity in radians
	 */
	function mean_obliquity_IAU2006(TT_JD) {
		return polynomial_value(IAU2006_obliquity_coefficients,
		// Interval between fundamental date J2000.0
		// and given date (JC).
		Julian_century(TT_JD)) * ARCSECONDS_TO_RADIANS;
	}

	/**
	 * 地球的平均轉軸傾角，平黃赤交角。 get mean obliquity of the ecliptic (Earth's axial tilt).
	 * 
	 * Reference 資料來源/資料依據: Laskar, J. (1986). "Secular Terms of Classical
	 * Planetary Theories Using the Results of General Relativity".
	 * 
	 * J. Laskar computed an expression to order T10 good to 0″.02 over 1000
	 * years and several arcseconds over 10,000 years.
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT), 適用於J2000.0起算前後各10000年的範圍內。
	 * 
	 * @returns {Number} obliquity in radians
	 */
	function mean_obliquity_Laskar(TT_JD) {
		return polynomial_value(Laskar_obliquity_coefficients,
		// J2000.0 起算的儒略萬年數
		Julian_century(TT_JD) / 100) * DEGREES_TO_RADIANS;
	}

	/**
	 * 地球的平均轉軸傾角，平黃赤交角。
	 * 
	 * @type {Function}
	 */
	var mean_obliquity = mean_obliquity_Laskar;

	/**
	 * 地球的轉軸傾角，真黃赤交角ε。<br />
	 * get obliquity of the ecliptic (Earth's axial tilt).
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @returns {Number}obliquity in radians
	 * 
	 * @see https://en.wikipedia.org/wiki/Axial_tilt
	 */
	function obliquity(TT_JD) {
		// 真黃赤交角是ε=ε0+Δε，Δε是交角章動。（詳見第21章 章動及黃赤交角）。
		return mean_obliquity(TT_JD) + nutation(TT_JD)[1];
	}

	_.obliquity = obliquity;

	// ------------------------------------------------------------------------------------------------------//
	// sidereal time. 恆星時

	/**
	 * Earth rotation angle (IAU 2000 model). 地球自轉角
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * IAU-SOFA: /src/era00.c
	 * 
	 * @param {Number}UT_JD
	 *            Julian date (JD of 日常生活時間 UT)
	 * 
	 * @returns {Number}Earth rotation angle (radians)
	 * 
	 * @see https://github.com/kanasimi/IAU-SOFA/blob/master/src/era00.c
	 */
	function IAU2000_ERA(UT_JD) {
		return TURN_TO_RADIANS * (
		// Fractional part of T (days).
		(UT_JD % 1)
		// Astronomical Almanac 2011:
		// Earth rotation angle (ERA) at J2000.0 UT1:
		// theta_0 = 0.7790572732640 revolutions
		+ 0.7790572732640
		// Astronomical Almanac 2011:
		// Rate of advance of ERA:
		// d(theta)/dUT1 = 1.00273781191135448 revs/UT1-day
		+ 0.00273781191135448
		// Days since fundamental epoch.
		* (UT_JD - J2000_epoch));
	}

	/**
	 * Earth rotation angle. 地球自轉角
	 * 
	 * @type {Function}
	 */
	_.ERA = IAU2000_ERA;

	/**
	 * terms for function IAU2006_GMST()
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * IAU-SOFA: /src/gmst06.c
	 * 
	 * @type {Array}
	 * @inner
	 * 
	 * @see https://github.com/kanasimi/IAU-SOFA/blob/master/src/gmst06.c
	 */
	var IAU2006_GMST_parameters = [ 0.014506, 4612.156534, 1.3915817,
			-0.00000044, -0.000029956, -0.0000000368 ].map(function(p) {
		return p * ARCSECONDS_TO_RADIANS;
	});

	/**
	 * Greenwich mean sidereal time (consistent with IAU 2006 precession).
	 * 
	 * Both UT1 and TT are required, UT1 to predict the Earth rotation and TT to
	 * predict the effects of precession.
	 * 
	 * his GMST is compatible with the IAU 2006 precession and must not be used
	 * with other precession models.
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * IAU-SOFA: /src/gmst06.c
	 * 
	 * @param {Number}UT_JD
	 *            Julian date (JD of 日常生活時間 UT)
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @returns {Number}Greenwich mean sidereal time (radians)
	 * 
	 * @see https://github.com/kanasimi/IAU-SOFA/blob/master/src/gmst06.c
	 */
	function IAU2006_GMST(UT_JD, TT_JD) {
		if (isNaN(TT_JD))
			TT_JD = TT_of(UT_JD);
		/**
		 * Julian centuries since J2000.0.<br />
		 * J2000.0 起算的儒略世紀數.
		 * 
		 * @type {Number}
		 */
		var T = Julian_century(TT_JD);

		// Greenwich mean sidereal time, IAU 2006.
		return IAU2000_ERA(UT_JD)
				+ polynomial_value(IAU2006_GMST_parameters, T);
	}

	/**
	 * terms for function Meeus_GMST()
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 88. formula 12.4
	 * 
	 * @type {Array}
	 * @inner
	 */
	var Meeus_GMST_parameters = [ 280.46061837,
			360.98564736629 * DAYS_OF_JULIAN_CENTURY, 0.000387933,
			-1 / 38710000 ].map(function(p) {
		return p * DEGREES_TO_RADIANS;
	});

	/**
	 * The mean sidereal time at Greenwich at Oh UT
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 88. formula 12.4
	 * 
	 * @param {Number}UT_JD
	 *            Julian date (JD of 日常生活時間 UT)
	 * 
	 * @returns {Number}Greenwich mean sidereal time (radians)
	 */
	function Meeus_GMST(UT_JD) {
		/**
		 * Julian centuries since J2000.0.<br />
		 * J2000.0 起算的儒略世紀數.
		 * 
		 * @type {Number}
		 */
		var T = Julian_century(UT_JD);
		return polynomial_value(Meeus_GMST_parameters, T).mod(TURN_TO_RADIANS);
	}

	/**
	 * Greenwich mean sidereal time. 平恆星時
	 * 
	 * @type {Function}
	 */
	var GMST = IAU2006_GMST;
	_.GMST = GMST;

	/**
	 * Greenwich apparent sidereal time, IAU 2006. Greenwich視恆星時
	 * 
	 * TODO: not yet done
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * IAU-SOFA: /src/gst06.c
	 * 
	 * @param {Number}UT_JD
	 *            Julian date (JD of 日常生活時間 UT)
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @returns {Number}Greenwich apparent sidereal time (radians)
	 * 
	 * @see https://github.com/kanasimi/IAU-SOFA/blob/master/src/gst06a.c
	 * @see https://github.com/kanasimi/IAU-SOFA/blob/master/src/gst06.c
	 */
	function IAU2006_GAST(UT_JD, TT_JD) {
		if (isNaN(TT_JD))
			TT_JD = TT_of(UT_JD);

		// Extract from the bias-precession-nutation matrix the X,Y
		// coordinates of the Celestial Intermediate Pole.
		var xy = iauBpn2xy(rnpb);
		// the CIO locator s, given X,Y, IAU 2006
		s = iauS06(TT_JD, xy);

		return IAU2000_ERA(UT_JD)
		// equation of the origins, given NPB matrix and s
		- iauEors(rnpb, s);
	}

	/**
	 * Greenwich apparent sidereal time. Greenwich視恆星時
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 88.
	 * 
	 * @param {Number}UT_JD
	 *            Julian date (JD of 日常生活時間 UT)
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @returns {Number}Greenwich apparent sidereal time (radians)
	 */
	function Meeus_GAST(UT_JD, TT_JD) {
		if (isNaN(TT_JD))
			TT_JD = TT_of(UT_JD);

		return GMST(UT_JD, TT_JD)
		// 赤經章動修正值 Δψ*cos(ε) 也稱作分點方程。
		+ nutation(TT_JD, true) * Math.cos(obliquity(TT_JD));
	}

	/**
	 * Greenwich apparent sidereal time. Greenwich視恆星時
	 * 
	 * @type {Function}
	 */
	var GAST = Meeus_GAST;
	_.GAST = GAST;

	// ------------------------------------------------------------------------------------------------------//
	// Sun's aberration. 太陽地心黃經光行差修正量。

	/**
	 * Sun's aberration. 太陽地心黃經光行差修正量。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * chapter 太陽位置計算 "太陽地心黃經光行差修正項" 式.<br />
	 * 
	 * @param {Number}R
	 *            日地距離(天文單位 AU), radius vector in AU。
	 * 
	 * @returns {Number} degree
	 * 
	 * @see https://en.wikipedia.org/wiki/Aberration_of_light
	 */
	function sun_aberration_low(R) {
		// 式中分子是光行差常數κ乘以a*(1-e²)，與24.5式的分子相同。
		// 因此24.10中的分子中其實是一個緩慢變化的數，在0年是20″.4893，在+4000年是20″.4904。
		return -20.4898 / DEGREES_TO_ARCSECONDS / R;
		// 24.10式本身不是一個嚴格的準確的運算式，因為它是假設地球軌道是不受攝動的標準橢圓。當受到攝動時，月球的攝動可引起0″.01的誤差。
	}

	/**
	 * Sun's aberration. 太陽地心黃經光行差修正量。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 167, 168. chapter 太陽位置計算.<br />
	 * 
	 * @param {Number}R
	 *            日地距離(天文單位 AU), radius vector in AU。
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @returns {Number} degree
	 * 
	 * @see https://en.wikipedia.org/wiki/Aberration_of_light
	 */
	function sun_aberration_high(R, TT_JD) {
		/**
		 * Julian millennia since J2000.0.<br />
		 * J2000.0 起算的儒略千年數.
		 * 
		 * @type {Number}
		 */
		var τ = Julian_century(TT_JD) / 10,
		// coefficients of Δλ
		coefficients = [];

		sun_aberration_variation.forEach(function(term) {
			var coefficient = 0;
			term.forEach(function(sub_term) {
				coefficient += sub_term[0]
						* Math.sin(sub_term[1] + sub_term[2] * τ);
			});
			coefficients.push(coefficient);
		});

		/**
		 * constant term of Sun's aberration
		 * 
		 * If needed with respect to the mean equinox of the date instead of to
		 * a fixed reference frame, the constant term 3548.193 should be
		 * replaced by 3548.330.
		 * 如果Δλ須是在Date黃道(瞬時黃道/當日黃道?)中的，則應把常數項3548.193換為3548.330
		 */
		coefficients[0] += sun_aberration_variation_constant;

		// Daily variation, in arcseconds, of the geocentric longitude
		// of the Sun in a fixed reference frame
		var Δλ = polynomial_value(coefficients, τ),
		//
		aberration = -AU_LIGHT_TIME / DEGREES_TO_ARCSECONDS * R * Δλ;

		if (library_namespace.is_debug(3))
			library_namespace.debug('aberration of radius vector ' + R
					+ ', JD: ' + TT_JD + ': ' + format_degrees(aberration)
					+ '. low-precision method: '
					+ format_degrees(sun_aberration_low(R)), 0);

		return aberration;
	}

	var sun_aberration = sun_aberration_high;

	// ------------------------------------------------------------------------------------------------------//
	// precession 歲差

	/**
	 * calculate general precession / precession of the ecliptic
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Kai Tang (2015). A long time span relativistic precession model of the
	 * Earth.
	 * 
	 * IAU 2006年將主要的部分重新命名為赤道歲差，而較微弱的成份命名為黃道歲差 (precession of the
	 * ecliptic)，但是兩者的合稱仍是綜合歲差 (general precession)，取代了分點歲差。
	 * 
	 * <q>在J2000.0的时候与P03岁差差大概几个角秒，主要由于周期拟合的时候，很难保证长期与短期同时精度很高。</q>
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Boolean}ecliptic
	 *            true: get precession of the ecliptic (黃道歲差). else: general
	 *            precession
	 * 
	 * @returns {Array} [ P, Q ] in degrees
	 */
	function precession(TT_JD, ecliptic) {
		/**
		 * Julian centuries since J2000.0.<br />
		 * J2000.0 起算的儒略世紀數.
		 * 
		 * @type {Number}
		 */
		var T = Julian_century(TT_JD),
		//
		terms = ecliptic ? 唐凯_ecliptic_precession_terms : 唐凯_precession_terms,
		//
		p_A = polynomial_value(terms.init[0], T),
		//
		ε_A = polynomial_value(terms.init[1], T);

		terms.forEach(function(term) {
			var p = term[4] * T;
			p_A += term[0] * Math.cos(p) + term[1] * Math.sin(p);
			if (term[2])
				ε_A += term[2] * Math.cos(p) + term[3] * Math.sin(p);
		});

		return [ p_A / DEGREES_TO_ARCSECONDS, ε_A / DEGREES_TO_ARCSECONDS ];
	}

	_.precession = precession;

	// ------------------------------------------------------------------------------------------------------//
	// nutation 章動

	/**
	 * IAU 2000B model nutation (地球章動) 修正值。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Nutation, IAU 2000B model.
	 * https://github.com/kanasimi/IAU-SOFA/blob/master/src/nut00b.c
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Boolean}Δψ_only
	 *            only get 黃經章動Δψ
	 * 
	 * @returns {Array} [ 黃經章動Δψ, 黃赤交角章動Δε ] (in radians)
	 * 
	 * @see http://www.neoprogrammics.com/nutations/nutations_1980_2000b/index.php
	 */
	function IAU2000B_nutation(TT_JD, Δψ_only) {
		/**
		 * Julian centuries since J2000.0.<br />
		 * J2000.0 起算的儒略世紀數.
		 * 
		 * @type {Number}
		 */
		var T = Julian_century(TT_JD),
		//
		parameters = [], Δψ = 0, Δε = 0;
		IAU2000B_nutation_parameters.forEach(function(parameter) {
			parameters.push((polynomial_value(parameter, T)
			//
			% TURN_TO_ARCSECONDS) * ARCSECONDS_TO_RADIANS);
		});

		library_namespace.debug('Julian centuries since J2000.0: ' + T, 4);

		for (var term,
		// Summation of luni-solar nutation series
		// (smallest terms first).
		index = IAU2000B_nutation_terms.length; index > 0;) {
			term = IAU2000B_nutation_terms[--index];
			var argument = 0;
			// 5: length of parameters
			for (var i = 0; i < 5; i++)
				// term[i] 常為0
				argument += term[i] * parameters[i];

			var _sin = Math.sin(argument), _cos = Math.cos(argument);
			Δψ += (term[5] + term[6] * T) * _sin + term[7] * _cos;
			if (!Δψ_only)
				Δε += (term[8] + term[9] * T) * _cos + term[10] * _sin;
		}

		// Convert from 0.1 microarcsec units to radians.
		i = ARCSECONDS_TO_RADIANS / 1e7;
		// Fixed offsets in lieu of planetary terms
		Δψ = Δψ * i + IAU2000B_nutation_offset_Δψ;
		if (!Δψ_only)
			Δε = Δε * i + IAU2000B_nutation_offset_Δε;

		library_namespace
				.debug(
				//
				'IAU2000B nutation 章動修正值 of JD' + TT_JD + ' ('
						+ library_namespace.JD_to_Date(TT_JD).format('CE')
						+ '): ' + Δψ / DEGREES_TO_RADIANS + '°, ' + Δε
						/ DEGREES_TO_RADIANS + '°', 3);
		return Δψ_only ? Δψ : [ Δψ, Δε ];
	}

	/**
	 * IAU 1980 model nutation (地球章動) 修正值。
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Boolean}Δψ_only
	 *            only get 黃經章動Δψ
	 * 
	 * @returns {Array} [ 黃經章動Δψ, 黃赤交角章動Δε ] (radians)
	 */
	function IAU1980_nutation(TT_JD, Δψ_only) {
		/**
		 * Julian centuries since J2000.0.<br />
		 * J2000.0 起算的儒略世紀數.
		 * 
		 * @type {Number}
		 */
		var T = Julian_century(TT_JD),
		//
		parameters = [], Δψ = 0, Δε = 0;
		IAU1980_nutation_parameters.forEach(function(parameter) {
			parameters.push((polynomial_value(parameter, T)
			//
			% TURN_TO_DEGREES) * DEGREES_TO_RADIANS);
		});

		// IAU1980_nutation_terms[6,8] 有乘以十倍了。
		T /= 10;

		IAU1980_nutation_terms.forEach(function(term) {
			var c, argument = 0, i = 0;
			// 5: parameters.length
			for (; i < 5; i++)
				// 正弦(計算Δψ用sine)的角度參數及餘弦(計算Δε用cosine)的角度參數是D、M、M'、F、Ω這5個基本參數的線性組合。
				// c常為0
				if (c = term[i])
					argument += c * parameters[i];

			Δψ += (term[5] + term[6] * T) * Math.sin(argument);
			if (!Δψ_only && (c = term[7] + term[8] * T))
				Δε += c * Math.cos(argument);
		});

		// 表中的係數的單位是0″.0001。
		T = ARCSECONDS_TO_RADIANS / 1e4;
		return Δψ_only ? Δψ * T : [ Δψ * T, Δε * T ];
	}

	var nutation = IAU2000B_nutation;
	_.nutation = nutation;

	// ------------------------------------------------------------------------------------------------------//
	// VSOP87 planets model

	/**
	 * 座標變換: 轉換動力學Date平黃道座標(Bretagnon的VSOP定義的)到 FK5 (第5基本星表, The Fifth
	 * Fundamental Catalogue) 坐標系統。<br />
	 * VSOP87 → FK5: translate VSOP87 coordinates to the FK5 frame.<br />
	 * 注意:會改變 coordinates!
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 219. formula 32.3
	 * 
	 * 太陽黃經☉及黃緯β是P.Bretagnon的VSOP行星理論定義的動力學黃道坐標。這個參考系與標準的FK5坐標系統(詳見20章)僅存在很小的差別。
	 * 可按以下方法把☉、β轉換到FK5坐標系統中,其中T是J2000起算的儒略世紀數,或T=10τ。
	 * J2000.0的VSOP黃道與J2000.0的FK5黃道存在一個很小的夾角 E = 0″.0554 左右，所以作以上修正。
	 * 
	 * @param {Object}coordinates {
	 *            L: mean dynamical ecliptical longitude in radians (弧度),<br />
	 *            B: mean dynamical the ecliptical latitude in radians (弧度) }
	 * @param {Number}τ
	 *            儒略千年數 Julian millennia since J2000.0.
	 * 
	 * @returns {Object}FK5 coordinates
	 * 
	 * @see http://www.astrosurf.com/jephem/astro/ephemeris/et520transfo_en.htm
	 */
	function dynamical_to_FK5(coordinates, τ) {
		// 先計算 L′ = L - 1°.397*T - 0°.00031*T²
		var _L = polynomial_value([ coordinates.L, -1.397 * DEGREES_TO_RADIANS,
				-0.00031 * DEGREES_TO_RADIANS ], 10 * τ),
		// cache
		cos_L = Math.cos(_L), sin_L = Math.sin(_L),
		// 然後計算L和B的修正值：
		ΔL = 0.03916 * ARCSECONDS_TO_RADIANS * (cos_L + sin_L)
				* Math.tan(coordinates.B) - 0.09033 * ARCSECONDS_TO_RADIANS;
		if (library_namespace.is_debug(3))
			library_namespace.debug('FK5 correction of object.L @ ' + τ + ' ≈ '
					+ coordinates.L + ' + '
					+ format_degrees(ΔL / DEGREES_TO_RADIANS));
		coordinates.L += ΔL;

		var ΔB = 0.03916 * ARCSECONDS_TO_RADIANS * (cos_L - sin_L);
		if (library_namespace.is_debug(3))
			library_namespace.debug('FK5 correction of object.B @ ' + τ + ' ≈ '
					+ coordinates.B + ' + '
					+ format_degrees(ΔB / DEGREES_TO_RADIANS));
		coordinates.B += ΔB;

		return coordinates;
	}

	/**
	 * 無用:因為 items[1,2] 已經是弧度。
	 * 
	 * @deprecated
	 */
	function initialize_VSOP87(subterms) {
		if (subterms.init)
			// 另一 thread 正初始化中。
			return;
		subterms.init = true;

		subterms.forEach(function(series) {
			series.forEach(function(items) {
				items[1] *= DEGREES_TO_RADIANS;
				items[2] *= DEGREES_TO_RADIANS;
			});
		});

		subterms.initialized = true;
		delete subterms.init;
	}

	/**
	 * terms for VSOP87 planets model used in function VSOP87()
	 * 
	 * full data:<br />
	 * ftp://ftp.imcce.fr/pub/ephem/planets/vsop87/README
	 * ftp://ftp.imcce.fr/pub/ephem/planets/vsop87/VSOP87D.ear
	 * 
	 * 金文敬. 2015. 太阳系行星和月球历表的发展.<br />
	 * 球坐標相對於瞬時平黃道和春分點為 VSOP87D 解。
	 * 
	 * TODO: VSOP2013, DE-431
	 * 
	 * see also:<br />
	 * JPL DE422:<br />
	 * http://ssd.jpl.nasa.gov/?ephemerides
	 * ftp://ssd.jpl.nasa.gov/pub/eph/planets/ascii/de422/
	 * 
	 * @inner
	 */
	var VSOP87_terms = Object.create(null);

	/**
	 * VSOP87 天體/行星的日心座標位置 (Heliocentric ecliptic spherical coordinates) 計算。<br />
	 * 得到行星在FK5坐標系統中的日心黃經L、黃緯B。<br />
	 * <br />
	 * does not include nutation or aberration.
	 * 
	 * 依 vsop87.doc 的說法，VSOP87D 已 apply precision:<br />
	 * ftp://ftp.imcce.fr/pub/ephem/planets/vsop87/vsop87.doc<br />
	 * The coordinates of the versions C and D are given in the frame defined by
	 * the mean equinox and ecliptic of the date. This frame is deduced from the
	 * previous one by precessional moving between J2000 and the epoch of the
	 * date.
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * chapter 太陽位置計算.
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {String}object
	 *            天體 (planets 行星).
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            {String|Array}options.terms: request terms.<br />
	 *            L: 日心黃經 the ecliptical longitude in radians (弧度) 真黃經，不是軌道經度,
	 *            NOT the orbital longitude<br />
	 *            B: 日心黃緯 the ecliptical latitude in radians (弧度)<br />
	 *            R: 行星到太陽的距離 the radius vector (distance to the Sun) in AU
	 *            (Astronomical Units)<br />
	 *            <br />
	 *            {Boolean}options.FK5: translate VSOP87 coordinates to the FK5
	 *            frame. default: true<br />
	 *            <br />
	 *            {Boolean}options.degrees: translate radians to degrees.
	 * 
	 * @returns {Object}FK5 coordinates { L:longitude in radians, B:latitude in
	 *          radians, R:distance in AU }
	 */
	function VSOP87(TT_JD, object, options) {
		/**
		 * Julian millennia since J2000.0.<br />
		 * J2000.0 起算的儒略千年數.
		 * 
		 * @type {Number}
		 */
		var τ = Julian_century(TT_JD) / 10,
		//
		coordinates = Object.create(null),
		//
		object_terms = VSOP87_terms[VSOP87.object_name(object)];
		if (!object_terms)
			throw new Error('VSOP87: Invalid object [' + object + ']');

		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var terms = options.terms;
		if (!terms)
			terms = 'LBR'.split('');
		else {
			if (!Array.isArray(terms))
				terms = [ terms ];
			if (options.FK5 !== false
					&& (terms.includes('L') || terms.includes('R'))) {
				if (!terms.includes('L'))
					terms.push('L');
				if (!terms.includes('B'))
					terms.push('B');
			}
		}

		terms.forEach(function(term_name) {
			var coefficients = [], subterms = object_terms[term_name];
			if (!subterms) {
				library_namespace.error('VSOP87: Invalid term name: ['
						+ term_name + ']');
				return;
			}

			// 無用:因為 items[1,2] 已經是弧度。
			if (false && !subterms.initialized) {
				initialize_VSOP87(subterms);
			}

			// series: 序列 L0,L1,..,B0,B1,..,R0,R1,..
			subterms.forEach(function(series) {
				coefficients.push(series.reduce(function(value, items) {
					if (false && items.length === 1)
						return value + items[0];
					// assert:
					// items.length
					// ===
					// 3
					return value + items[0] * Math.cos(
					// items:
					// 三個數字項
					// [A,B,C]
					// 每項(表中各行)的值計算表達式是：
					// A*cos(B+C*τ);
					items[1] + items[2] * τ);
				}, 0));
			});

			coordinates[term_name] =
			// L=(L0+L1*τ+L2*τ²+L3*τ³+L4*τ⁴+L5*τ⁵)/10⁸
			// (倍數: 10⁻⁸)
			polynomial_value(coefficients, τ);
			// 倍數
			if (object_terms.multiplier > 0)
				coordinates[term_name] *= object_terms.multiplier;
			library_namespace.debug(
			//
			object + '.' + term_name + ' @ ' + TT_JD + ' ≈ '
			//
			+ (term_name === 'R' ? coordinates[term_name] + '  AU'
			//
			: format_degrees(normalize_degrees(
			//
			coordinates[term_name] / DEGREES_TO_RADIANS,
			//
			term_name === 'B'))) + ' (coefficients: ' + coefficients.join(', ')
					+ ')', 3);
		});

		if (options.FK5 !== false)
			dynamical_to_FK5(coordinates, τ);

		// 單位轉換。
		if (options.degrees) {
			if (coordinates.L)
				coordinates.L /= DEGREES_TO_RADIANS;
			if (coordinates.B)
				coordinates.B /= DEGREES_TO_RADIANS;
		}

		return terms.length > 1 ? coordinates : coordinates[terms[0]];
	}

	_.VSOP87 = VSOP87;

	/**
	 * 正規化天體/行星名稱。
	 * 
	 * @param {String}object
	 *            天體 (planets 行星).
	 * 
	 * @returns {String|Undefined} 行星名稱
	 */
	VSOP87.object_name = function(object) {
		if (typeof object === 'string')
			return object.trim().toLowerCase();
	};

	/**
	 * 增加指定天體/行星的計算數據，提供給模組內部函數使用。
	 * 
	 * @param {String}object
	 *            天體 (planets 行星).
	 * @param {Array}terms
	 *            計算數據.
	 */
	function VSOP87_add_terms(object, terms) {
		object = VSOP87.object_name(object);
		if (object === solar_terms_object)
			// reset solar_terms_cache
			solar_terms_cache = [];
		VSOP87_terms[object] = terms;
	}

	VSOP87.add_terms = VSOP87_add_terms;

	/**
	 * 載入指定天體/行星的計算數據後，執行 callback。提供給模組外部函數使用。
	 * 
	 * @param {String|Array}object
	 *            天體 (planets 行星).
	 * @param {Function}callback
	 *            callback function.
	 */
	function VSOP87_load_terms(object, callback) {
		if (!object)
			return callback(succeed);

		var paths = [], objects = [];
		if (!Array.isArray(object))
			object = [ object ];
		object.forEach(function(o, index) {
			o = VSOP87.object_name(o);
			if (!(o in VSOP87_terms)) {
				objects.push(o);
				paths.push(library_namespace.get_module_path(
				//
				module_name + library_namespace.env.path_separator + 'VSOP87_'
						+ o));
			}
		});
		library_namespace.run(paths, function() {
			var failed = [];
			objects.forEach(function(o, index) {
				if (!VSOP87_terms[o])
					failed.push(o);
			});
			if (failed.length === 0)
				failed = undefined;
			library_namespace.info(
			//
			'VSOP87_load_terms: ' + (failed
			//
			? 'Failed to load [' + failed + ']'
			// resources
			: 'resource files of [' + objects + '] loaded.'));
			if (typeof callback === 'function')
				callback(failed);
		});
	}

	VSOP87.load_terms = VSOP87_load_terms;

	/**
	 * 轉換 VSOP87 file @ node.js。
	 * 
	 * TODO: parse VSOP87 file
	 * 
	 * @param {String}file_name
	 *            source file name
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項
	 * 
	 * @since 2015/4/15 ‏‎17:46:12, 2015/4/18 21:36:12
	 */
	function convert_VSOP87_file(file_name, options) {
		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var encoding = options.encoding || 'ascii',
		// 需要先設定 fs = require('fs');
		// https://nodejs.org/api/fs.html
		fs = require('fs');

		fs.readFile(file_name, {
			encoding : encoding
		}, function(error, data) {
			if (error)
				throw error;

			// parse VSOP87 file.
			data = data.split(/\n/);

			var object, type, group,
			//
			terms = Object.create(null);

			data.forEach(function(line) {
				if (!line)
					return;
				var fields = line.trim().split(/\s+/);
				if (isNaN(fields[0])) {
					if (!object)
						// e.g., 'earth'
						object = fields[3].toLowerCase();
					// e.g., 'L', 'B',
					// 'R'.
					var t = fields[6][fields[5]];
					group = [];
					if (t === type)
						terms[type].push(group);
					else
						terms[type = t] = [ group ];

					console.log(object + ' ' + type + ' ' + fields[7] + ' '
							+ fields[8] + ' terms');
					return;
				}

				if (false && terms[type].length === 1 && group.length === 0)
					console.log(fields);
				fields = fields.slice(-3);
				fields.forEach(function(f, index) {
					fields[index] = +f;
				});

				// check
				if (false && fields.length !== 3)
					throw fields;
				if (!options.limit || group < options.limit)
					group.push(fields);
			});

			var new_line = '\n', prefix = '// auto-generated from '
			//
			+ (options.name || 'VSOP87')
			// e.g., 'D' for VSOP87D.
			+ (options.type || '') + new_line + library_namespace.Class + '.'
					+ (options.name || 'VSOP87') + '.add_terms(',
			//
			postfix = options.postfix || new_line + ');';
			fs.writeFile(options.name + '_' + object + '.js', prefix
					+ JSON.stringify(object)
					+ ','
					+ new_line
					+ JSON.stringify(terms)
							.replace(/(\]\],)/g, '$1' + new_line) + postfix, {
				encoding : encoding
			});

		});
	}

	VSOP87.convert = convert_VSOP87_file;

	// ------------------------------------------------------------------------------------------------------//
	// 天體/行星位置計算

	/**
	 * planet / Astronomical objects or celestial objects<br />
	 * Warning: terms of object and Earth should loaded first.
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 225. Example 33.a with full VSOP87
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {String}object
	 *            天體 (planets 行星).
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項
	 * 
	 * @returns {Object}coordinates
	 */
	function object_coordinates(TT_JD, object, options) {
		// 前置處理。
		if (!options && library_namespace.is_Object(object) && object.object)
			object = (options = object).object;
		else if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var τ0, τ = 0, rectangular, object_heliocentric,
		//
		coordinates = Object.create(null),
		// light-time error in days
		error = options.error || 1e-6;

		// corrected for the light-time and the aberration together at
		// once
		// 一次性修正光行時及光行差。
		do {
			// assert: terms of object and Earth are loaded.
			// JD時的天體/行星日心瞬時黃道座標。
			object_heliocentric = VSOP87(TT_JD - τ, object, {
				FK5 : false
			});
			// JD時的地球日心黃道座標。
			var earth_heliocentric = VSOP87(TT_JD - τ, solar_terms_object, {
				FK5 : false
			}),
			// planet's distance to the Earth, 行星到地球的距離.
			Δ = (rectangular = spherical_to_rectangular(object_heliocentric, {
				base : earth_heliocentric,
				distance : true
			})).distance;
			if (τ === 0) {
				// real distance at TT_JD in AU
				coordinates.Δ0 = Δ;
				// D日心瞬時黃道
				// heliocentric dynamical ecliptic coordinate system
				// @see function Coordinates()
				coordinates.D = object_heliocentric;
			}
			τ0 = τ;
			// effect of light-time, 光線從行星到達地球所需的時間.
			τ = AU_LIGHT_TIME * Δ;

			library_namespace.debug('τ-τ0 = ' + Math.abs(τ - τ0));
		} while (Math.abs(τ - τ0) > error);

		// apparent distance at TT_JD in AU
		coordinates.Δ = Δ;

		// S日心視黃道 heliocentric ecliptic coordinate system
		// @see function Coordinates()
		coordinates.S = object_heliocentric;

		// rectangular: 該天體的地心直角黃道座標
		// → geocentric: 該天體的地心黃道座標(球座標)
		var geocentric = rectangular_to_spherical(rectangular);

		// corrections for reduction to the FKS system
		/**
		 * Julian millennia since J2000.0.<br />
		 * J2000.0 起算的儒略千年數.
		 * 
		 * @type {Number}
		 */
		τ = Julian_century(TT_JD) / 10;
		// replacing L by λ, and B by β.
		geocentric = dynamical_to_FK5({
			L : geocentric[0],
			B : geocentric[1]
		}, τ);

		// 修正地球章動 nutation。
		τ = nutation(TT_JD);
		// G地心視黃道 apparent geocentric ecliptic coordinates:
		// longitude λ and latitude β in radians
		coordinates.λ = geocentric.L + τ[0];
		coordinates.β = geocentric.B + τ[1];

		get_horizontal(coordinates, TT_JD, options);

		// 單位轉換。
		if (options.degrees) {
			coordinates.λ /= DEGREES_TO_RADIANS;
			coordinates.β /= DEGREES_TO_RADIANS;
		}

		return coordinates;
	}

	_.object_coordinates = object_coordinates;

	// ------------------------------------------------------------------------------------------------------//
	// solar coordinates 太陽位置(坐標) & 二十四節氣 (solar terms)

	/**
	 * 低精度分點和至點的時刻, 太陽視黃經λ為0°或90°或180°或270°. 在 1951–2050 CE 的誤差 < 1分.
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * chapter 分點和至點.<br />
	 * 
	 * @param {Integer}year
	 *            年
	 * @param {Integer}index
	 *            0–3: [ 3月春分 0°, 6月夏至 90°, 9月秋分 180°, 12月冬至 270° ]<br />
	 *            aka. [ March equinox, June solstice, September equinox,
	 *            December solstice ]
	 * 
	 * @returns {Number} Julian date (JD of 天文計算用時間 TT)
	 */
	function equinox(year, index, no_fix) {
		// year is an integer; other values for year, would give
		// meaningless results!
		var TT_JD = (year |= 0) < 1000 ? equinox_terms_before_1000
				: equinox_terms_after_1000;
		// 計算相應的"平"分點或"平"至點的時刻。
		TT_JD = polynomial_value(TT_JD[index |= 0], (year < 1000 ? year
				: year - 2000) / 1000);

		if (no_fix)
			// get 太陽分點和至點"平"黃經。
			return TT_JD;

		/**
		 * Julian centuries since J2000.0.<br />
		 * J2000.0 起算的儒略世紀數.
		 * 
		 * @type {Number}
		 */
		var T = Julian_century(TT_JD),
		//
		W = (35999.373 * T - 2.47) * DEGREES_TO_RADIANS,

		// 太陽平黃經→太陽視黃經
		// 要計算的分點或至點時刻(儒略曆書時,即力學時）表達為：
		λ = TT_JD + 0.00001 *
		// JDE0 + 0.00001 S / Δλ 日
		equinox_periodic_terms.reduce(function(S, terms) {
			return S + terms[0] * Math.cos(terms[1] + terms[2] * T);
		}, 0) /
		// Δλ
		(1 + 0.0334 * Math.cos(W) + 0.0007 * Math.cos(2 * W));

		// λ: 太陽黃經☉是Date黃道分點座標(瞬時黃道/當日黃道?)的真幾何黃經。
		// 要取得視黃經λ，還應加上精準的黃經章動及光行差。
		// TODO: 黃經周年光行差修正量：-20″.161 (公式(24.10)), 黃經章動效果：Δψ =
		// -12″.965
		// (詳見第22章), 轉到 FK5 系統的修正值(-0″.09033) (公式(24.9))
		// 光行差 aberration
		// 章動 nutation

		// ΔT(year, month)
		λ -= ΔT(year, index * 3 + 3.5) / ONE_DAY_SECONDS;

		return λ;
	}

	_.equinox = equinox;

	/**
	 * solar coordinates 太陽位置(坐標)計算。<br />
	 * ObsEcLon (Observer ecliptic lon. & lat.) or PAB-LON (PHASE angle &
	 * bisector) @ HORIZONS?
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 166–169. Example 25.b
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            {Boolean}options.degrees: translate radians to degrees.<br />
	 *            {Boolean}options.km: translate AU to km.<br />
	 * 
	 * @returns {Object}coordinates { apparent:太陽視黃經(度), λ:地心黃經(radians),
	 *          β:地心黃緯β(radians), Δ:日地距離(AU), L:黃經 longitude(radians), B:黃緯
	 *          latitude(radians), R:距離 radius vector(AU) }
	 */
	function solar_coordinates(TT_JD, options) {
		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		// heliocentric coordinates. 計算日心黃道坐標中地球的位置。
		var coordinates = VSOP87(TT_JD, solar_terms_object);

		// 日心黃道坐標中地球的位置 → 地心黃道坐標中太陽的位置
		// 弧度單位日心黃經L → 地心黃經(geocentric longitude)λ(度)
		// Jean Meeus 文中以 "☉" 表示此處之 λ。
		var λ = coordinates.L + TURN_TO_RADIANS / 2,
		// 弧度單位日心黃緯B → 地心黃緯β(度)
		β = -coordinates.B;

		// 太陽的視黃經 (apparent longitude)λ(度)（受光行差及章動影響）
		// Jean Meeus 文中以 "λ" 表示此處之視黃經 apparent。
		//
		// https://en.wikipedia.org/wiki/Apparent_longitude
		// Apparent longitude is used in the definition of
		// equinox and solstice.
		// 節氣以太陽視黃經為準。
		// ** 問題:但中國古代至點以日長為準。兩者或可能產生出入？
		var apparent = λ / DEGREES_TO_RADIANS
		// 修正太陽光行差 aberration。
		+ sun_aberration(coordinates.R, TT_JD)
		// 修正地球章動 nutation。
		+ nutation(TT_JD, true) / DEGREES_TO_RADIANS;

		// https://en.wikipedia.org/wiki/Ecliptic_coordinate_system#Spherical_coordinates
		Object.assign(coordinates, {
			// geocentric
			λ : normalize_radians(λ),
			β : normalize_radians(β, true),
			Δ : coordinates.R,

			// apparent longitude
			apparent : normalize_degrees(apparent)
		// TODO: apparent latitude
		});

		get_horizontal(coordinates, TT_JD, options);

		// 單位轉換。
		if (options.degrees) {
			coordinates.λ /= DEGREES_TO_RADIANS;
			coordinates.β /= DEGREES_TO_RADIANS;
			coordinates.L /= DEGREES_TO_RADIANS;
			coordinates.B /= DEGREES_TO_RADIANS;
		}
		if (options.km) {
			// 1000: 1 km = 1000 m
			coordinates.Δ *= AU_TO_METERS / 1000;
			coordinates.R *= AU_TO_METERS / 1000;
		}

		return coordinates;
	}

	_.solar_coordinates = solar_coordinates;

	/**
	 * 取得指定年分 year 年，指定太陽視黃經角度之 Julian date。
	 * 
	 * @param {Integer}year
	 *            year 年(CE)
	 * @param {Number}degrees
	 *            0–less than 360.<br />
	 *            angle in degrees from March equinox of the year.<br />
	 *            指定太陽視黃經角度，自當年黃經0度(春分)開始。
	 * 
	 * @returns {Number} Julian date (JD of 日常生活時間 UT)
	 */
	function JD_of_solar_angle(year, degrees) {
		var offset, apparent,
		// index: 下界 index of 分點和至點, 0–3
		index = degrees / EQUINOX_SOLSTICE_DEGREES | 0,
		// JD 近似值(下界)。
		TT_JD = equinox(year, index, true);
		// 經測試，有時每天太陽的視黃經 (apparent longitude) 可能會增加近 .95°
		// NOT 360/365.25

		// 太陽的視黃經最大變化量。
		// http://jpkc.haie.edu.cn/jpkc/dqgl/content.asp?classid=17&id=528
		// 在遠日點，地球公轉慢，太陽每日黃經差Δλ也慢，為57′
		// 在近日點，地球公轉快，太陽每日黃經差Δλ也快，為61′

		if (degrees % EQUINOX_SOLSTICE_DEGREES > 0)
			TT_JD += ((index === 3 ? equinox(year + 1, 0) : equinox(year,
					index + 1)) - TT_JD)
					// 以內插法(線性插值)取得近似值。
					* (degrees - index * EQUINOX_SOLSTICE_DEGREES)
					/ EQUINOX_SOLSTICE_DEGREES;

		// 最多趨近 JD_of_solar_angle.max_calculations 次。
		for (index = JD_of_solar_angle.max_calculations; index-- > 0;) {
			// apparent in degrees.
			apparent = solar_coordinates(TT_JD).apparent;
			// 由公式(26.1)得到對“大約時間”的修正量。
			// +58 sin (k·90° - λ) (26.1)
			offset = 58 * Math.sin((degrees - apparent) * DEGREES_TO_RADIANS);
			// ↑ 58: maybe 59 = 360/365.25*60 ??
			// https://www.ptt.cc/bbs/sky/M.1175584311.A.8B8.html

			if (false)
				library_namespace.debug('index ' + index + ': apparent: '
						+ format_degrees(apparent) + ', offset in days: '
						+ offset);

			if (Math.abs(offset) < JD_of_solar_angle.error)
				// 當 error 設定得很小時，似乎會達到固定循環。
				break;
			// adapt 修正量。
			TT_JD += offset;
		}

		// apply ΔT: TT → UT.
		return UT_of(TT_JD);
	}

	/**
	 * 最多計算(趨近) (JD_of_solar_angle.max_calculations) 次。
	 * 
	 * @type Integer > 0
	 */
	JD_of_solar_angle.max_calculations = 20 | 0;

	/**
	 * 可接受之最大誤差。<br />
	 * 即使設為 0，最多也只會計算 (JD_of_solar_angle.max_calculations) 次。<br />
	 * 當 error 設定得很小時，似乎會達到固定循環。因此此值不應該設為 0，否則以所採用方法將不會收斂。
	 * 
	 * @type Number > 0
	 */
	JD_of_solar_angle.error = 2e-10;

	_.JD_of_solar_angle = JD_of_solar_angle;

	/**
	 * 定氣：取得指定年分 year 年，指定節氣/分點和至點之 Julian date。
	 * 
	 * from http://ssd.jpl.nasa.gov/horizons.cgi#results<br />
	 * DE-0431LE-0431 GEOCENTRIC<br />
	 * Date__(UT)__HR:MN:SC.fff CT-UT ObsEcLon ObsEcLat<br />
	 * 0001-Mar-22 21:45:35.500 10518.071036 359.9999962 -0.0001845<br />
	 * 0001-Mar-22 21:45:36.000 10518.071036 0.0000018 -0.0001845<br />
	 * <br />
	 * 2015-Mar-20 22:45:10.000 67.185603 359.9999944 0.0000095<br />
	 * 2015-Mar-20 22:45:10.500 67.185603 0.0000001 0.0000095
	 * 
	 * 注意: 1979/1/20 (中曆1978年12月22日) is 大寒 (300°), not 實曆 1979/1/21 (according
	 * to 中央氣象局 http://www.cwb.gov.tw/V7/astronomy/cdata/calpdf/calpdf.htm,
	 * 中国科学院紫金山天文台 公农历查询 http://almanac.pmo.ac.cn/cx/gzn/index.htm and 香港天文台
	 * http://www.weather.gov.hk/gts/time/conversionc.htm ). According to
	 * HORIZONS (DE-431), it seems at about 1979/1/20 23:59:55.55.
	 * 
	 * @param {Integer}year
	 *            year 年(CE)
	 * @param {Number|String}index
	 *            index. 0: 春分
	 * @param {Number}[type]
	 *            1: 分點和至點, others (default): 二十四節氣，<br />
	 *            皆自當年黃經0度(春分)開始。
	 * 
	 * @returns {Number} Julian date (JD of 日常生活時間 UT)
	 * 
	 * @see http://blog.csdn.net/orbit/article/details/7910220
	 */
	function solar_term_JD(year, index, type) {
		var angle;

		if (typeof index === 'string' && NOT_FOUND !==
		//
		(angle = SOLAR_TERMS_NAME.indexOf(index)))
			index = angle, type = 0;

		if (type === 1) {
			angle = (index | 0) * TURN_TO_DEGREES / EQUINOX_SOLSTICE_COUNT;
		} else {
			if (!index) {
				angle = 0;
			} else if (isNaN(angle = index) && (NOT_FOUND ===
			//
			(angle = SOLAR_TERMS_NAME.indexOf(index)))) {
				library_namespace.error(
				//
				'solar_term_JD: Invalid solar term [' + index + ']!');
				return;
			}
			index = angle;
			angle *= DEGREES_BETWEEN_SOLAR_TERMS;
		}

		// assert:
		// angle is now angle (0–less than 360),
		// from March equinox of year.
		return JD_of_solar_angle(year, angle);
	}

	_.solar_term_JD = solar_term_JD;

	/**
	 * solar_terms 使用之 object name.
	 * 
	 * @type {String}
	 * @inner
	 */
	var solar_terms_object = 'earth',
	/**
	 * cache.
	 * 
	 * solar_terms_cache[ year ] = [ 春分JD, 清明JD, 穀雨JD, ... 24個節氣 ]
	 * 
	 * @type {Array}
	 * @inner
	 */
	solar_terms_cache = [];

	/**
	 * 取得指定 Julian date 之二十四節氣名，或已經過日數、物候(七十二候, 初候/二候/三候, 初候/次候/末候)。
	 * 
	 * TODO: 候應, 二十四番花信風 http://baike.baidu.com/view/54438.htm
	 * 
	 * @param {Number}UT_JD
	 *            Julian date (JD of 日常生活時間 UT)
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            options.days: 回傳 [ 節氣年 year (以"春分"分年, 非立春後才過年!), 節氣序 index,
	 *            已經過日數/剩下幾日 ]。<br />
	 *            options.pentads: 亦標示七十二候 (物候, 72 pentads)<br />
	 *            options.time: 取得節氣名時，亦取得交節時刻。
	 * 
	 * @returns {String|Undefined|Array}
	 * 
	 * @see http://koyomi8.com/24sekki.htm
	 */
	function solar_term_of_JD(UT_JD, options) {

		// return the nearest (test_next: thie next one) solar
		// term JD.
		function get_cache(test_next) {
			if (!date)
				date = library_namespace.JD_to_Date(UT_JD);
			year = date.getFullYear();

			index = apparent / DEGREES_BETWEEN_SOLAR_TERMS | 0;
			if (test_next && ++index === SOLAR_TERMS_COUNT)
				// 本年春分
				index = 0;

			// 17: SOLAR_TERMS_NAME.indexOf('大雪')
			// assert: 大雪以及之前的節氣，都會落在本年度內。
			// 2000 CE 前後千年間，小寒或大寒之前分年。
			else if (index > 17
			// 3: assert: 要算作前一年的節氣，都會在3月前。
			&& date.getMonth() <= 3 - 1)
				// 每一年春分前末幾個節氣，算前一年的。
				year--;

			var cache = solar_terms_cache[year], term_JD;
			if (!cache)
				// 初始化本年度資料。
				solar_terms_cache[year] = cache = [];

			if (!(term_JD = cache[index]))
				// 填入節氣JD
				cache[index] = term_JD = solar_term_JD(year, index);

			return term_JD;
		}

		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var index, days, date, year,
		// apparent in degrees
		apparent = solar_coordinates(TT_of(UT_JD)).apparent;

		// get days, 回傳已經過幾日。
		if (options.days) {
			// 先取得 距離上一節氣之日數。
			days = get_cache(true) - UT_JD | 0;
			// days === 0: 當天交節。
			if (days !== 0 && options.days !== 'next')
				// 'next': 距離下一節氣之日數。天文節氣 剩餘日數。
				index--, days = Math.ceil(UT_JD - get_cache());
			// others (passed days): 距離上一節氣之日數。天文節氣 經過日數。
			return [ year, index, days ];
		}

		if (DEGREES_BETWEEN_SOLAR_TERMS
		// assert: 超過2度，就不會是在同一天。
		- (apparent % DEGREES_BETWEEN_SOLAR_TERMS) < 2) {
			// UT_JD 再過一下下便是節氣。
			// 測試本日0時是否距離下一節氣發生時間1天內。
			// assert: 此範圍內不可能為物候。
			days = get_cache(true) - UT_JD;

			// UT_JD 將被視為當地時間當日0時!
			if (0 <= days && days < 1) {
				// 初候
				index = SOLAR_TERMS_NAME[index];
				if (options.time) {
					index += ' ' + ((days *= ONE_DAY_HOURS) | 0) + ':';
					// options.time > 1 : add seconds.
					if (options.time > 1)
						index += ((days = (days % 1) * 60) | 0) + ':';
					// index += ((days % 1) * 60).to_fixed(1);
					index += Math.round((days % 1) * 60);
				}
				return index;
			}
			return;
		}

		if (options.pentads
		// UT_JD 將被視為當地時間當日0時，因此只要節氣在 UT_JD 之前，皆表示本日非節氣，僅能測試物候。
		// || (apparent % DEGREES_BETWEEN_SOLAR_TERMS < 2)
		) {
			// days = 與前一個節氣之間距。
			days = UT_JD - get_cache();
			// 七十二候 (物候, 72 pentads)
			// 初候 二候 三候
			// 初候 中候 末候
			// http://koyomi8.com/sub/72kou.htm
			// 5: 又五日
			// 節氣之後每五日一候，非採用 360/72 = 5° 一候。
			if (days <= 5 && 4 < days)
				return SOLAR_TERMS_NAME[index] + ' 二候';
			if (4 + 5 < days && days <= 5 + 5)
				return SOLAR_TERMS_NAME[index] + ' 三候';

			// return;
		}
	}

	_.solar_term_of_JD = solar_term_of_JD;

	// ----------------------------------------------------------------------------------------------------------------------------------------------//
	// 應用功能:輔助以節氣為年首之曆法

	var
	// copy from CeL.data.date.
	/** {Number}一整天的 time 值。should be 24 * 60 * 60 * 1000 = 86400000. */
	ONE_DAY_LENGTH_VALUE = new Date(0, 0, 2) - new Date(0, 0, 1);
	var
	// 小寒(19) 1月5-7日交節，以春分分年的情況，已在下一年。
	solar_term_starts_year = SOLAR_TERMS_NAME.indexOf('小寒'),
	// solar_term_calendar_cache[term index / minute_offset]
	// = { CE year : Date value }
	solar_term_calendar_cache = [];

	/**
	 * 取得 calendar 年首。
	 * 
	 * @param {Integer}CE_year
	 *            CE year
	 * 
	 * @returns {Integer} Date value
	 */
	function solar_term_calendar_year_start(CE_year) {
		var year_start = this.cache[CE_year |= 0];
		if (year_start)
			return year_start;

		year_start = midnight_of(solar_term_JD(
		// 保證 year_start 與 CE_year 在同一年:
		// 小寒(19) 1月5-7日交節，之後應該計算前一年的節氣。
		// 警告:此演算法於小寒不在隔年的情況，將失效。
		this.term_index < solar_term_starts_year ? CE_year : CE_year - 1,
				this.term_index), this.minute_offset, true);

		library_namespace.debug('CE ' + CE_year + ' '
				+ SOLAR_TERMS_NAME[this.term_index] + ' begins on '
				+ year_start.format(), 2);
		return this.cache[CE_year]
		// cache[CE year] = term Date value of year
		= year_start = year_start.getTime();
	}

	/**
	 * Date → [ year, days of year ]
	 * 
	 * @param {Date}date
	 *            指定日期。
	 * 
	 * @returns {Array} [ (CE year), (days counts from the first day) ]
	 */
	function solar_term_calendar_year_of(date) {
		var CE_year = date.getFullYear(),
		//
		month = date.getMonth(), days;

		// (this.month_start) 月之前，位在前一年。
		if (month < this.month_start
		//
		|| (days = date - this.year_starts(CE_year)) < 0)
			days = date - this.year_starts(--CE_year);
		// assert: days >= 0

		// [ CE_year, (days counts from the first day) ]
		return [ CE_year, days / ONE_DAY_LENGTH_VALUE ];
	}

	/**
	 * 輔助以節氣為年首曆法之 handler。
	 * 
	 * handler(year) → start of year
	 * 
	 * handler.year_of(date) → [ year, days]
	 * 
	 * @param {String|Integer}term
	 *            solar term name / index
	 * @param {Integer}[minute_offset]
	 *            indicate the time zone
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項
	 * 
	 * @returns {Function} handler
	 * 
	 * @see solar_term_calendar_year_start(CE_year),
	 *      solar_term_calendar_year_of(date)
	 */
	function solar_term_calendar(term, minute_offset, options) {
		var term_index = typeof term === 'string' ? SOLAR_TERMS_NAME
				.indexOf(term) : term;
		if (!SOLAR_TERMS_NAME[term_index]) {
			library_namespace.error(
			//
			'solar_term_calendar: Invalid term: [' + term + ']');
			return;
		}

		var cache = term_index + '/' + (minute_offset |= 0);
		cache = solar_term_calendar_cache[cache]
		//
		|| (solar_term_calendar_cache[cache]
		//
		= Object.create(null));

		// 不動到原 options。
		options = Object.assign(Object.create(null), options);

		var handler = solar_term_calendar_year_start.bind(options);
		handler.year_of = solar_term_calendar_year_of.bind(options);

		Object.assign(options, {
			term_index : term_index,
			minute_offset : minute_offset,
			cache : cache,
			year_starts : handler,
			month_start : (term_index - solar_term_starts_year)
					.mod(SOLAR_TERMS_NAME.length) / 2 | 0
		});

		return handler;
	}

	_.solar_term_calendar = solar_term_calendar;

	// ----------------------------------------------------------------------------------------------------------------------------------------------//
	// 應用功能:需配合 'data.date'。

	var
	// 起始年月日。年月日 starts form 1.
	// 基本上與程式碼設計合一，僅表示名義，不可更改。
	START_YEAR = 1, START_MONTH = 1, START_DATE = 1,
	// set normal month count of a year.
	// 月數12: 每年有12個月。
	MONTH_COUNT = 12,
	// = 2. assert: 為整數
	SOLAR_TERMS_MONTH_RATE = SOLAR_TERMS_NAME.length / MONTH_COUNT | 0,
	// 21
	立春NO = SOLAR_TERMS_NAME.indexOf('立春') | 0,
	// 立春年_OFFSET = 5
	立春年_OFFSET = (MONTH_COUNT + START_MONTH) * SOLAR_TERMS_MONTH_RATE - 立春NO
			| 0;

	/**
	 * 取得立春年歲首。
	 * 
	 * TODO: 以立春與節氣排曆。計算以節氣(實為十二節)分年月。每年以立春交節時刻為界。<br />
	 * 十二節年月, 節氣年月, 立春年月
	 * 
	 * 立春，指太陽到達黃經315°時，屬相（生肖）以立春作為起始點。 中國古時春節曾專指立春，也被視為一年的開始。
	 * 
	 * @param {Date|Integer}date
	 *            指定年份或日期
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項
	 * 
	 * @returns {Date} 指定年份或日期所在立春年之歲首(立春時刻)
	 */
	function 立春年(date, options) {
		if (!isNaN(date) && -1000 < date && date < 3000) {
			// get JD of CE year (date)
			date = [ date, 1 ];
		}

		if (Array.isArray(date)) {
			// [ CE 立春節氣年, 立春節氣月 ]
			// get JD of CE year (date)
			if ((date[1] = date[1] * SOLAR_TERMS_MONTH_RATE - 立春年_OFFSET) < 0)
				date[1] += SOLAR_TERMS_NAME.length, date[0]--;
			date = solar_term_JD(date[0], date[1]);
			// options: return JD
			return options ? date : library_namespace.JD_to_Date(date);
		}

		if (!library_namespace.is_Date(date))
			return;

		if (options) {
			// options: return [ CE 立春節氣年, 立春節氣月 ]
			date = solar_term_of_JD(
			// 回傳 [ 節氣年 year (以"春分"分年, 非立春後才過年!),
			// 節氣序 index, 已經過日數/剩下幾日 ]。
			library_namespace.Date_to_JD(date), {
				days : true
			});
			date.pop();
			date[1] = (date[1] + 立春年_OFFSET) / SOLAR_TERMS_MONTH_RATE | 0;
			// 月數12: 每年有12個月
			if (date[1] > MONTH_COUNT)
				date[1] -= MONTH_COUNT, date[0]++;
			return date;
		}

		// options: return (CE 立春節氣年)
		var year = date.getFullYear(), month = date.getMonth();
		// 快速判別:立春為公曆每年2月3至5日之間
		if (month !== 1)
			return month < 1 ? year - 1 : year;
		// +1: 當天24時之前交節，依舊得算在當日。
		return library_namespace.Date_to_JD(date) + 1
		// 就算正好等於，本日JD也應該算前一年的。
		<= solar_term_JD(year - 1, 立春NO) ? year - 1 : year;
	}

	// CeL.立春年(2001).format('CE');
	_.立春年 = 立春年;

	// ------------------------------------------------------------------------------------------------------//

	var TYPE_SOLAR = 1, TYPE_LUNAR = 2,
	// 89: Lunar Eclipses Saros Series 7
	MAX_SAROS_SERIES = 89;

	/**
	 * Get the saros series index of JD.
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Number}[type]
	 *            type = 1(TYPE_SOLAR): solar, 2(TYPE_LUNAR): lunar
	 * 
	 * @returns {Array} [ type, saros series index, #NO of series ]
	 */
	function saros(TT_JD, type) {
		if (!type)
			return saros(TT_JD, TYPE_SOLAR)
			//
			|| saros(TT_JD, TYPE_LUNAR);

		var data = type === TYPE_SOLAR ? solar_saros_remainder
				: lunar_saros_remainder, series, remainder = TT_JD
				.mod(saros_days),
		// get TT
		index = data[0].search_sorted(remainder, data[1]), NOm1;
		if (!index && remainder < data[0][0])
			// 若是比最小的還小，則當作最後一個。
			index = data[1].at(-1);
		if (index && 0 <=
		// NOm1: #NO - 1
		(NOm1 = Math.round((TT_JD - index[1]) / saros_days))
				&& MAX_SAROS_SERIES > NOm1) {
			var series = [ type, index[0], NOm1 + 1 ],
			// mean TT
			TT = index[1] + NOm1 * saros_days;
			// 2: 別差太多，最起碼應在2天內。
			if (Math.abs(TT_JD - TT) < 2) {
				series.TT = TT;
				return series;
			}
		}
	}

	/**
	 * Get the JD of specified saros series and NO.
	 * 
	 * @param {Natural}type
	 *            type = 1: solar, 2: lunar
	 * @param {Natural}series
	 *            saros series
	 * @param {Natural}[NO]
	 *            NO of saros series
	 * 
	 * @returns {Number}JD (UT) of specified saros series and NO
	 */
	function saros_JD(type, series, NO) {
		series = (type === TYPE_SOLAR
		//
		? solar_saros : lunar_saros)[series];
		if (isNaN(series))
			return;

		// JD: TT
		var JD = series
				+ (0 < NO && NO <= MAX_SAROS_SERIES ? (NO - 1) * saros_days : 0);
		// JD: UT
		JD = library_namespace.Julian_day.to_YMD(UT_of(JD));

		// JD: UT
		JD = lunar_phase([ JD[0], JD[1] ],
		//
		type === TYPE_SOLAR ? 0 : 2);

		// TODO: 此處得到的是朔望時間，而非食甚時間。應進一步處理之。

		return JD;
	}

	saros.JD = saros_JD;
	_.saros = saros;

	// TODO: metonic series
	// https://en.wikipedia.org/wiki/Solar_eclipse_of_March_20,_2015#Metonic_series

	// ------------------------------------------------------------------------------------------------------//
	// LEA-406a, LEA-406b lunar model & periodic terms

	/**
	 * 預設使用 type，'a' or 'b'。
	 * 
	 * a 相當耗資源。當前 HORIZONS 已使用 DE-431 LE-431，與 LEA-406 及 ELP/MPP02 相差不小。何況 a, b
	 * 常僅差不到 10秒，因此似無必要使用 LEA-406a。
	 */
	LEA406.default_type = 'b';

	var LEA406_name = 'LEA-406',
	/**
	 * the mean longitude of the Moon referred to the moving ecliptic and mean
	 * equinox of date (Simon et al. 1994). (formula 9)
	 * 
	 * Simon (1994): "Numerical expressions for precession formulae and mean
	 * elements for the Moon and the planets"
	 * 
	 * (b.3) Mean elements referred to the mean ecliptic and equinox of date
	 * (P_1 = 5028″.8200/cy)
	 * 
	 * But modified: t as 儒略千年數 Julian millennia since J2000.0.
	 * 
	 * LEA406_V_coefficients in arcseconds.
	 * 
	 * @inner
	 */
	LEA406_V_coefficients = [ 218.31664563 * DEGREES_TO_ARCSECONDS,
			17325643723.0470, -527.90, 6.665, -0.5522 ];

	/**
	 * Gets coordinates of lunar (geocentric dynamical ecliptic coordinates).
	 * Using full LEA-406a or LEA-406b model.<br />
	 * 計算月亮位置(地心瞬時黃道坐標)，採用完整的 LEA-406a, LEA-406b。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * S. M. Kudryavtsev, Long-term harmonic development of lunar ephemeris,
	 * Astronomy & Astrophysics 471 (2007), pp. 1069-1075.
	 * http://www.eas.slu.edu/GGP/kudryavtsev/LEA-406.zip
	 * <q>This is 9–70 times better than the accuracy of the latest analytical theory of lunar motion ELP/MPP02, and the number of terms in the new development is less than that in ELP/MPP02.</q>
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            {Boolean}options.degrees: translate radians to degrees.<br />
	 *            {Boolean}options.km: translate AU to km.<br />
	 *            {String|Array}options.terms: request terms.<br />
	 *            V: 地心黃經 in radians. ecliptic longitude reckoned along the
	 *            moving ecliptic from the mean equinox of date<br />
	 *            U: 地心黃緯 in radians. ecliptic latitude reckoned from the moving
	 *            ecliptic<br />
	 *            R: 地心距離 in AU. geocentric distance<br />
	 * 
	 * @returns {Object} { V:longitude in radians, U:latitude in radians,
	 *          R:distance in AU }
	 * 
	 * @see http://www.gautschy.ch/~rita/archast/ephemeriden.html
	 * @see https://github.com/infinet/lunar-calendar/
	 */
	function LEA406(TT_JD, options) {
		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = typeof options === 'string' ? {
				terms : options
			} : Object.create(null);

		/**
		 * Julian millennia since J2000.0.<br />
		 * J2000.0 起算的儒略千年數.
		 * 
		 * @type {Number}
		 */
		var τ = Julian_century(TT_JD) / 10,
		// τ²
		τ2 = τ * τ, terms = options.terms,
		//
		warn_term = !options.ignore_term,
		/**
		 * spherical coordinates of its centre:
		 * 
		 * r: 地心距離 in AU. (geocentric distance)
		 * 
		 * V: 從曆元平春分點沿移動黃道(瞬時黃道?)的地心黃經 in radians. (ecliptic longitude reckoned
		 * along the moving ecliptic from the mean equinox of date)
		 * 
		 * U: 移動黃道(瞬時黃道?)計算的地心黃緯 in radians. (ecliptic latitude reckoned from
		 * the moving ecliptic)
		 */
		coordinates = Object.create(null);

		library_namespace.debug(
		//
		TT_JD + ': τ: ' + τ + ', τ²: ' + τ2, 3);

		if (!Array.isArray(terms)) {
			if (!terms || typeof terms !== 'string') {
				terms = 'VUR';
				// 有什麼就用什麼。
				warn_term = false;
			}
			terms = terms.split('');
		}

		// Geocentric spherical coordinates of the Moon r, V, U are
		// expanded to Poisson series of the form
		terms.forEach(function(term) {
			var type = options.type || LEA406.default_type,
			//
			subterms = LEA406_terms[term + type];
			if (!subterms) {
				// try another one.
				type = type === 'a' ? 'b' : 'a';
				subterms = LEA406_terms[term + type];
			}
			if (!subterms) {
				if (warn_term)
					library_namespace.error(
					//
					'LEA406: Invalid term name: [' + term
							+ ']. You may need to load it first.');
				return;
			}

			var sum = 0,
			// R (formula 6),
			// V (formula 7), U (formula 8)
			operator = term === 'R' ? Math.cos : Math.sin;

			subterms.forEach(function(T, index) {
				// T = [ coefficients[4 in arcseconds],
				// Amp0,Amp1,Phase1,Amp2,Phase2 ]
				var ω = polynomial_value(T[0], τ);
				// Amp 常為 0
				if (T[1])
					sum += T[1] * operator(ω);
				if (T[2])
					sum += T[2] * operator(ω + T[3]) * τ;
				if (T[4])
					sum += T[4] * operator(ω + T[5]) * τ2;

				if (false && isNaN(sum)) {
					console.error(T);
					throw '內部錯誤 @ index ' + index + ': ' + T;
				}
			});
			library_namespace.debug(
			//
			TT_JD + '.' + term + ': ' + sum, 3);

			// Amp_to_integer: see convert_LEA406()
			sum /= Amp_to_integer;

			if (term === 'V')
				sum += polynomial_value(LEA406_V_coefficients, τ);
			// R is now km. e.g., 384399.
			// V, U is now arcseconds.
			if (term !== 'R')
				// default: V, U in arcseconds → radians
				sum *= ARCSECONDS_TO_RADIANS;
			coordinates[term] = sum;
		});

		/**
		 * 2451545.5-64.183889/86400 ≈ 2451545.499257131
		 * <q>
		{source: DE-0431LE-0431}

		Date__(UT)__HR:MN:SC.fff Date_________JDUT            CT-UT    ObsEcLon    ObsEcLat
		2013-Jun-02 06:33:23.000 2456445.773182870        67.184868 359.9999798   3.8258600
		2013-Jun-02 06:33:23.500 2456445.773188658        67.184868   0.0000545   3.8258553
		</q>
		 * 360-359.9999798=0.0000202
		 * <code>2456445.773182870+(2456445.773188658-2456445.773182870)*202/(202+545)+67.184868/86400</code> ≈
		 * 2456445.7739620376 TT
		 * 
		 * CeL.LEA406.default_type = 'a'; CeL.LEA406.load_terms('Va');
		 * CeL.LEA406.load_terms('Ua'); CeL.LEA406.load_terms('Ra');
		 * <code>CeL.find_root(function(TT){return CeL.normalize_radians(CeL.LEA406(TT).V,true);},2456445,2456446)</code> ≈
		 * 2456445.774202571 TT
		 * 
		 * (.774202571-.7739620376)*86400≈20.78208575999696
		 * 
		 * <code>CeL.find_root(function(TT){return CeL.normalize_radians(CeL.LEA406(TT,{FK5:false}).V,true);},2456445,2456446)</code> ≈
		 * 2456445.7742006825 TT
		 * 
		 * (.7742006825-.7739620376)*86400≈20.618919359992915
		 * 
		 * no FK5 較接近。但仍有誤差 20.6 s
		 */
		if (false && options.FK5 !== false) {
			// τ: tmp
			τ = dynamical_to_FK5({
				L : coordinates.V,
				B : coordinates.U
			}, τ);
			coordinates.V = τ.L;
			coordinates.U = τ.B;
		}

		// 單位轉換。
		if (options.degrees) {
			// V, U in radians → degrees
			if (coordinates.V)
				coordinates.V /= DEGREES_TO_RADIANS;
			if (coordinates.U)
				coordinates.U /= DEGREES_TO_RADIANS;
		}
		// R is now km. e.g., 384399.
		if (!options.km && coordinates.R)
			// default: R in km → AU.
			// 1000: 1 km = 1000 m
			coordinates.R /= AU_TO_METERS / 1000;

		return terms.length === 1
		//
		? coordinates[terms[0]] : coordinates;
	}

	_.LEA406 = LEA406;

	/**
	 * LEA406_terms[Va,Ua,Ra;Vb,Ub,Rb] = {terms}
	 * 
	 * @type {Object}
	 * @inner
	 */
	var LEA406_terms = Object.create(null);

	/**
	 * 增加指定項目的計算數據，提供給模組內部函數使用。
	 * 
	 * @param {String}term_name
	 *            項目名稱 (Va,Ua,Ra;Vb,Ub,Rb).
	 * @param {Array}terms
	 *            計算數據.
	 */
	function LEA406_add_terms(term_name, terms) {
		// 初始化: 將 sin() 之引數全部轉成 radians。
		terms.forEach(function(T) {
			// T = [ coefficients[4 in arcseconds],
			// Amp0,Amp1,Phase1,Amp2,Phase2 ]
			T[0].forEach(function(coefficient, index) {
				T[0][index] *= ARCSECONDS_TO_RADIANS;
			});
			// T[2–5] 可能為了節省大小，而為 undefined!
			var i = 3;
			T[i] = T[i] ? T[i] * ARCSECONDS_TO_RADIANS : 0;
			i = 5;
			T[i] = T[i] ? T[i] * ARCSECONDS_TO_RADIANS : 0;
		});
		// .reverse(): smallest terms first
		LEA406_terms[term_name] = terms.reverse();
	}

	LEA406.add_terms = LEA406_add_terms;

	/**
	 * 載入指定項目的計算數據後，執行 callback。提供給模組外部函數使用。
	 * 
	 * @param {String}term_name
	 *            項目名稱 (V,U,R).
	 * @param {Function}callback
	 *            callback.
	 */
	function LEA406_load_terms(term_name, callback) {
		var type;
		if (term_name.length === 2) {
			type = term_name.charAt(1);
			term_name = term_name.charAt(0);
		} else
			type = LEA406.default_type;
		if ((term_name + type) in LEA406_terms) {
			if (typeof callback === 'function')
				callback();
			return;
		}

		var name = LEA406_name + type + '-' + term_name;
		library_namespace.run(library_namespace.get_module_path(module_name
		//
		+ library_namespace.env.path_separator + name), [ function() {
			library_namespace.info(
			// resources
			'LEA406_load_terms: resource files of [' + name
			//
			+ '] loaded, ' + LEA406_terms[term_name + type].length
			// Poisson series
			+ ' terms.');
		}, callback ]);
	}

	LEA406.load_terms = LEA406_load_terms;

	/**
	 * 確定已經載入那些 terms。
	 * 
	 * @param {String}[term_name]
	 *            項目名稱 (V,U,R).
	 * 
	 * @returns {Array|String} 已載入 terms。
	 */
	function LEA406_loaded(term_name) {
		if (!term_name)
			return Object.keys(LEA406_terms);
		// ab: LEA-406a, LEA-406b
		var terms = [], types = 'ab'.split('');
		types.forEach(function(type) {
			if ((term_name + type) in LEA406_terms)
				terms.push(type);
		});
		return terms.join('');
	}

	LEA406.loaded = LEA406_loaded;

	/**
	 * 轉換 LEA-406 (LEA-406a, LEA-406b) file。
	 * 
	 * need data.native, run @ node.js
	 * 
	 * TODO: parse LEA-406 file
	 * 
	 * @param {String}file_name
	 *            source file name
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項
	 * 
	 * @since 2015/4/20
	 */
	function convert_LEA406(file_name, options) {
		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var encoding = options.encoding || 'ascii',
		//
		floating = 9,
		// 需要先設定 fs = require('fs');
		// https://nodejs.org/api/fs.html
		fs = require('fs');

		fs.readFile(file_name, {
			encoding : encoding
		}, function(error, data) {
			if (error)
				throw error;

			// parse LEA-406 file.
			data = data.split(/\n/);
			// Lines 1-8 give a short description of the data included
			// to the file.
			data.splice(0, 8);

			var terms = [];

			data
					.forEach(function(line) {
						if (!line)
							return;

						var fields = line.trim().replace(/(\d)-/g, '$1 -')
								.split(/\s+/);
						if (fields.length !== 21 || isNaN(fields[0]))
							throw line;
						var i = 15;
						// 將 Amp 轉整數: Amp *= 1e7
						// (表格中小數7位數)。
						fields[i] = Math.round(fields[i] * Amp_to_integer);
						i++;
						fields[i] = Math.round(fields[i] * Amp_to_integer);
						i++;
						fields[i] = Math.round(fields[i] * Amp_to_integer);
						i++;

						// 轉整數以作無誤差加減。
						fields[i] = Math.round(fields[i] * 1e12);
						i++;
						fields[i] = Math.round(fields[i] * 1e12);
						i++;
						fields[i] = Math.round(fields[i] * 1e12);

						fields[19] -= fields[18];
						fields[20] -= fields[18];

						i = 18;
						// φ: Phase1, Phase2 → in arcseconds
						// φ: Phase 有12位數，*DEGREES_TO_ARCSECONDS 之後最多10位數
						fields[i] = (fields[i]
						// / 1e2 / 1e10 = / 1e12
						* (DEGREES_TO_ARCSECONDS / 1e2) / 1e10).to_fixed(10);
						i++;
						fields[i] = (fields[i]
						//
						* (DEGREES_TO_ARCSECONDS / 1e2) / 1e10).to_fixed(10);
						i++;
						fields[i] = (fields[i]
						//
						* (DEGREES_TO_ARCSECONDS / 1e2) / 1e10).to_fixed(10);

						var coefficients = [ fields[18], 0, 0, 0, 0 ];

						if (false) {
							coefficients.forEach(function(i, index) {
								coefficients[index]
								//
								= new library_namespace.data.math.integer(0);
							});
							coefficients[0]
							//
							= new library_namespace.data.math.integer(
									fields[18]);
							coefficients[0].divide(1e12, 12);
						}

						terms.push([ coefficients,
						// Amp0,Amp1,Phase1,Amp2,Phase2
						fields[15], fields[16], fields[16] ? fields[19] : 0,
								fields[17], fields[17] ? fields[20] : 0 ]);
						i = 1;

						for (var multiplier; i <= 14; i++)
							if (multiplier = +fields[i])
								convert_LEA406_arguments[i]
								//
								.forEach(function(a, index) {
									// a 為整數，coefficients 小數位數最多即為[0]，6位數。
									// coefficients[index]=(coefficients[index]+(a*multiplier).to_fixed(6)).to_fixed(6);
									coefficients[index] += a * multiplier;
									if (false) {
										coefficients[index].add(
										//
										(new library_namespace.data.math
										//
										.integer(a)).multiply(multiplier));
									}
									if (false &&
									//
									!Number.isSafeInteger(coefficients[index]))
										throw 'Out of range from: ' + fields
												+ '\ncoefficients: '
												+ coefficients;
								});
						coefficients.forEach(function(c, index) {
							// coefficients[index]=c*DEGREES_TO_RADIANS;
							// coefficients[index]=c.to_fixed(6);
							coefficients[index] = c.to_fixed();
							// coefficients[index]=coefficients[index].valueOf();
						});
					});

			var name = options.name || LEA406_name,
			//
			new_line = '\n', prefix = '// auto-generated from '
			//
			+ name
			// e.g., 'a' for LEA-406a.
			+ (options.type || '') + new_line + library_namespace.Class + '.'
					+ name.replace(/-/g, '') + '.add_terms(',
			//
			postfix = options.postfix || new_line + ');';
			fs.writeFile(name + (options.type || '') + '-' + options.term
					+ '.js', prefix
					+ JSON.stringify(options.term + (options.type || ''))
					+ ','
					+ new_line
					+ JSON.stringify(terms).replace(/,0/g, ',').replace(
							/,+\]/g, ']').replace(/(\]\],)/g, '$1' + new_line)
					// .replace(/(\],)/g,
					// '$1' +
					// new_line)
					+ postfix, {
				encoding : encoding
			});
		});
	}

	LEA406.convert = convert_LEA406;

	// ------------------------------------------------------------------------------------------------------//
	// lunar coordinates 月亮位置(坐標)

	/**
	 * lunar coordinates, moon's coordinates 月亮位置(地心黃道坐標)計算。<br />
	 * get lunar angle, moon's angle. 僅將 LEA-406 修正地球章動 nutation。
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            {Boolean}options.degrees: translate radians to degrees.<br />
	 *            {Boolean}options.km: translate AU to km.<br />
	 * 
	 * @returns {Object} { V:longitude in radians, U:latitude in radians,
	 *          R:distance in AU }
	 */
	function lunar_coordinates(TT_JD, options) {
		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var coordinates = LEA406(TT_JD, 'FK5' in options ? {
			FK5 : options.FK5
		} : null);

		if (('V' in coordinates) || ('U' in coordinates)) {
			// var n = nutation(TT_JD);
			if ('V' in coordinates) {
				coordinates.λ = coordinates.V;
				// V, U in radians

				/**
				 * 修正經度 of 月亮光行時間 light-time correction (Moon's
				 * light-time)。忽略對緯度之影響。
				 * 
				 * Reference 資料來源/資料依據:<br />
				 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
				 * p. 337. formula 49.1.<br />
				 * <q>the constant term of the effect of the light-time (-0″.70)</q>
				 * 
				 * -0″.704:
				 * <q>formula in: G.M.Clemence, J.G.Porter, D.H.Sadler (1952): "Aberration in the lunar ephemeris", Astronomical Journal 57(5) (#1198) pp.46..47; but computed with the conventional value of 384400 km for the mean distance which gives a different rounding in the last digit.</q>
				 * http://en.wikipedia.org/wiki/New_moon
				 * 
				 * @see http://blog.csdn.net/orbit/article/details/8223751
				 * @see http://en.wikipedia.org/wiki/Light-time_correction
				 * @see http://lifesci.net/pod/bbs/board.php?bo_table=B07&wr_id=52
				 */
				var light_time = -0.70 * ARCSECONDS_TO_RADIANS;
				if (false)
					(function() {
						/**
						 * 錯誤的方法:
						 * 
						 * @deprecated
						 */
						// coordinates.R in AU.
						var r = coordinates.R * AU_TO_METERS
								|| LUNAR_DISTANCE_M;
						// 地球半徑。
						r -= TERRA_RADIUS_M;
						// 1000: 1 km = 1000 m (CELERITAS in m/s)
						light_time = -r / CELERITAS * TURN_TO_DEGREES
								/ ONE_DAY_SECONDS;
						library_namespace.debug(
						//
						'月亮經度光行差 of JD' + TT_JD + ' ('
						//
						+ library_namespace.JD_to_Date(
						//
						UT_of(TT_JD)).format('CE') + '): '
								+ format_degrees(light_time), 3);
					});
				// 經測試， LEA-406 似已修正月亮光行時、地球章動
				// coordinates.λ += light_time;

				/**
				 * 修正地球章動 nutation: LEA-406 基於 LE406，未包含 nutations, librations。
				 * 
				 * @see http://www.projectpluto.com/jpl_eph.htm
				 * 
				 * DE405 : Created May 1997; includes both nutations and
				 * librations. Referred to the International Celestial Reference
				 * Frame. Covers JED 2305424.50 (1599 DEC 09) to JED 2525008.50
				 * (2201 FEB 20)
				 * 
				 * DE406 : Created May 1997; includes neither nutations nor
				 * librations. Referred to the International Celestial Reference
				 * Frame. Spans JED 0625360.5 (-3000 FEB 23) to 2816912.50
				 * (+3000 MAY 06)
				 */
				// 經測試， LEA-406 似已修正月亮光行時、地球章動
				// coordinates.λ += n[0];
				coordinates.λ = normalize_radians(coordinates.λ);
			}
			if ('U' in coordinates) {
				coordinates.β = coordinates.U;
				// V, U in radians.
				// 修正地球章動 nutation。
				// 經測試， LEA-406 似已修正月亮光行時、地球章動
				// coordinates.β += n[1];
				coordinates.β = normalize_radians(coordinates.β, true);
			}
		}

		if ('R' in coordinates) {
			coordinates.Δ = coordinates.R;

			if (coordinates.β && coordinates.λ) {
				get_horizontal(coordinates, TT_JD, options);
			}

			// 單位轉換。
			if (options.km) {
				// R in AU → km.
				// 1000: 1 km = 1000 m
				coordinates.R *= AU_TO_METERS / 1000;
				coordinates.Δ *= AU_TO_METERS / 1000;
			}
		}

		// 單位轉換。
		if (options.degrees) {
			// V, U in radians → degrees
			if ('V' in coordinates) {
				coordinates.V /= DEGREES_TO_RADIANS;
				coordinates.λ /= DEGREES_TO_RADIANS;
			}
			if ('U' in coordinates) {
				coordinates.U /= DEGREES_TO_RADIANS;
				coordinates.β /= DEGREES_TO_RADIANS;
			}
		}

		return coordinates;
	}

	_.lunar_coordinates = lunar_coordinates;

	// lunar_phase_of_JD_cache[TT_JD] = degrees;
	var lunar_phase_of_JD_cache = [];

	/**
	 * get the longitudinal angle between the Moon and the Sun.<br />
	 * 計算 JD 時的月日視黃經差（月-日）。<br />
	 * 趨近 the elongation of Moon，但忽略緯度影響。
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Boolean}normalize_360
	 *            正規化成 0°–360°，而非 -180°–180°。
	 * 
	 * @returns {Number}angle in degrees
	 */
	function lunar_phase_angle_of_JD(TT_JD, normalize_360) {
		var degrees;

		if (String(TT_JD) in lunar_phase_of_JD_cache)
			degrees = lunar_phase_of_JD_cache[TT_JD];
		else if (!isNaN(degrees =
		// 可以忽略章動的影響。
		lunar_coordinates(TT_JD).λ / DEGREES_TO_RADIANS
				- solar_coordinates(TT_JD).apparent))
			lunar_phase_of_JD_cache[TT_JD] = degrees;

		if (!isNaN(degrees))
			degrees = normalize_degrees(degrees, !normalize_360);
		return degrees;
	}

	_.lunar_phase_angle_of_JD = lunar_phase_angle_of_JD;

	/**
	 * 平朔望月長度 in days. 日月合朔週期。
	 * 
	 * @type {Number}
	 * 
	 * @see mean_lunar_phase_coefficients
	 */
	var mean_lunar_phase_days = 29.530588861,
	/**
	 * 平月相的不變時間參數。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 349. Chapter 49 Phases of the Moon. formula 49.1.<br />
	 * 
	 * @type {Array}
	 * 
	 * @inner
	 */
	mean_lunar_phase_coefficients = [ 2451550.09766,
	// 29.530588861 * k, but k = 1236.85 * T.
	29.530588861 * 1236.85, 0.00015437, -0.000000150, 0.00000000073 ],
	// Sun's mean anomaly at time JDE: 太陽平近點角： in radians
	eclipse_coefficients_M = [ 2.5534, 29.10535670 * 1236.85, -0.0000014,
			-0.00000011 ].map(degrees_to_radians),
	// Moon's mean anomaly: (Mʹ, M′) 月亮的平近點角： in radians
	eclipse_coefficients_Mm = [ 201.5643, 385.81693528 * 1236.85, 0.0107582,
			0.00001238, -0.000000058 ].map(degrees_to_radians),
	// Moon's argument of latitude: 月亮的緯度參數： in radians
	eclipse_coefficients_F = [ 160.7108, 390.67050284 * 1236.85, -0.0016118,
			-0.00000227, 0.000000011 ].map(degrees_to_radians),
	// Longitude of the ascending node of the lunar orbit:
	// 月亮軌道升交點經度： in radians
	eclipse_coefficients_Ω = [ 124.7746, -1.56375588 * 1236.85, 0.0020672,
			0.00000215 ].map(degrees_to_radians),
	// p. 338. (47.6)
	eclipse_coefficients_E = [ 1, -0.002516, -0.0000074 ],
	// p. 380.
	eclipse_coefficients_A1 =
	//
	[ 299.77, 0.107408 * 1236.85, -0.009173 ];

	/**
	 * 平月相的時間，已修正了太陽光行差及月球光行時間。<br />
	 * The times of the mean phases of the Moon, already affected by the Sun's
	 * aberration and by the Moon's light-time
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 349. formula 49.1.<br />
	 * 
	 * @param {Number}year_month
	 *            帶小數點的年數，例如1987.25表示1987年3月末。
	 * @param {Integer}phase
	 *            0:朔0°, 1:上弦90°, 2:望180°, 3:下弦270°
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            {Boolean}options.nearest: 取得最接近之月相時間。
	 * 
	 * @returns {Number} Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @see https://github.com/soniakeys/meeus/blob/master/eclipse/eclipse.go
	 */
	function mean_lunar_phase(year_month, phase, options) {
		phase /= 4;
		if (Array.isArray(year_month))
			year_month = year_month[0] + (year_month[1] - 1) / 12;
		/**
		 * 12.36853:
		 * <q>DAYS_OF_JULIAN_CENTURY / 100 / 29.530588861 = 12.368530872148396</q>
		 */
		var k = (year_month - 2000) * 12.36853,
		// 取 year_month 之後，第一個 phase。
		// Any other value for k will give meaningless results
		T = Math.floor(k) + phase;
		if (options && options.nearest && T - k > .5)
			// 取前一個。
			k = T - 1;
		else
			// 取之後最接近的。
			k = T;

		// T是J2000.0起算的儒略世紀數，用下式可得到足夠的精度：
		T = k / 1236.85;

		var TT_JD = polynomial_value(mean_lunar_phase_coefficients, T);
		if (!options || !options.eclipse
		//
		|| phase !== 0 && phase !== .5)
			return TT_JD;

		var
		// Moon's argument of latitude: 月亮的緯度參數： in radians
		F = normalize_radians(polynomial_value(eclipse_coefficients_F, T), true),
		//
		F_ = F / DEGREES_TO_RADIANS;

		/**
		 * p. 380.
		 * 
		 * If F differs from the nearest multiple of 180° by less than 13.9
		 * degrees, then there is certainly an eclipse; if the difference is
		 * larger than 21°.0, there is no eclipse; between these two values, the
		 * eclipse is uncertain at this stage and the case must be examined
		 * further.
		 */
		if (90 - Math.abs(90 - Math.abs(F_)) > 21.0)
			return TT_JD;

		var
		// Sun's mean anomaly at time JDE: 太陽平近點角： in radians
		M = polynomial_value(eclipse_coefficients_M, T),
		// Moon's mean anomaly: (Mʹ, M′) 月亮的平近點角： in radians
		Mm = polynomial_value(eclipse_coefficients_Mm, T),
		// Longitude of the ascending node of the lunar orbit:
		// 月亮軌道升交點經度： in radians
		Ω = polynomial_value(eclipse_coefficients_Ω, T),
		// p. 338. (47.6)
		// 表中的這些項包含了了M(太陽平近點角)，它與地球公轉軌道的離心率有關，就目前而言離心率隨時間不斷減小。由於這個原因，振幅A實際上是個變數(並不是表中的常數)，角度中含M或-M時，還須乘上E，含2M或-2M時須乘以E的平方進行修正。E的運算式如下：
		// The coefficient, not the argument of the sine or cosine,
		// should be multiplied by E.
		E = polynomial_value(eclipse_coefficients_E, T),
		// p. 380.
		F1 = F - 0.02665 * DEGREES_TO_RADIANS * Math.sin(Ω),
		// p. 380.
		A1 = polynomial_value(eclipse_coefficients_A1, T)
		//
		* DEGREES_TO_RADIANS;

		// 取得最大食的時間(對於地球一般是日食)，使用(47.1)平會合時間加上以下修正(單位是天)。
		var ΔJD = (phase === 0
		// 日食
		? -0.4075 * Math.sin(Mm) + 0.1721 * E * Math.sin(M)
		// 月食
		: -0.4065 * Math.sin(Mm) + 0.1727 * E * Math.sin(M))
		// p. 380.
		+ 0.0161 * Math.sin(2 * Mm) - 0.0097 * Math.sin(2 * F1) + 0.0073 * E
				* Math.sin(Mm - M) - 0.0050 * E * Math.sin(Mm + M) - 0.0023
				* Math.sin(Mm - 2 * F1) + 0.0021 * E * Math.sin(2 * M) + 0.0012
				* Math.sin(Mm + 2 * F1) + 0.0006 * E * Math.sin(2 * Mm + M)
				- 0.0004 * Math.sin(3 * Mm) - 0.0003 * E * Math.sin(M + 2 * F1)
				+ 0.0003 * Math.sin(A1) - 0.0002 * E * Math.sin(M - 2 * F1)
				- 0.0002 * E * Math.sin(2 * Mm - M) - 0.0002 * Math.sin(Ω);

		// p. 381. 高精度的日月位置計算需要幾百個項才能得到。
		var P = 0.2070 * E * Math.sin(M) + 0.0024 * E * Math.sin(2 * M)
				- 0.0392 * Math.sin(Mm) + 0.0116 * Math.sin(2 * Mm) - 0.0073
				* E * Math.sin(Mm + M) + 0.0067 * E * Math.sin(Mm - M) + 0.0118
				* Math.sin(2 * F1),
		// p. 381. 高精度的日月位置計算需要幾百個項才能得到。
		Q = 5.2207 - 0.0048 * E * Math.cos(M) + 0.0020 * E * Math.cos(2 * M)
				- 0.3299 * Math.cos(Mm) - 0.0060 * E * Math.cos(Mm + M)
				+ 0.0041 * E * Math.cos(Mm - M),
		// p. 381.
		W = Math.abs(Math.cos(F1)),
		// p. 381. Gamma
		// 在日食情況下，γ表示月影軸到地心的最小距離，單位是地球赤道半徑。
		// 在月食的情況下，γ表示月亮中心到地影軸的最小距離，單位是地球赤道半徑。γ是正還是負，取決於月亮中心經過地影軸的北邊或是南邊。
		γ = (P * Math.cos(F1) + Q * Math.sin(F1)) * (1 - 0.0048 * W),
		// p. 381.
		u = 0.0059 + 0.0046 * E * Math.cos(M) - 0.0182 * Math.cos(Mm) + 0.0004
				* Math.cos(2 * Mm) + -0.0005 * Math.cos(M + Mm),
		//
		abs_γ = Math.abs(γ),
		// 計算日月食的特性值。
		feature = {
			/**
			 * 日月食食點出現在月亮軌道的升交點 ascending node / 降交點 descending node。
			 * 
			 * If F is near 0° or 360°, the eclipse occurs near the Moon's
			 * ascending node. If F is near 180°, the eclipse takes place near
			 * the descending node of the Moon's orbit.
			 */
			node : Math.abs(F_) < 22 ? 'ascending' : 'descending',
			γ : γ,
		};

		if (phase === 0) {
			// 日食。地球的扁率是0.9972。
			// the oblateness of the Earth it is 0.9972.
			// 0.9972 may vary between 0.9970 and 0.9974 from one
			// eclipse to another.
			if (abs_γ < 0.9972) {
				// 日食中心是：在地球表面上存在一條日食中央線，影軸在地表經過的那條線。
				/**
				 * u表示月亮影錐在基平面上的半徑，單位也是地球半徑。基平面指：經過地心並且垂直月亮影軸的平面。半影錐在基平面上的半徑是u+0.5461
				 * 
				 * The quantity u denotes the radius of the Moon's umbral cone
				 * in the fundamental plane, again in units of the Earth's
				 * equatorial radius. The radius of the penumbral cone in the
				 * fundamental plane is u + 0.5461.
				 */
				// 影錐半徑
				feature.umbral_radius = u;
				// 半影錐半徑
				feature.penumbral_radius = u + 0.5461;
				// 對於有中心的日食，食的類型由以下規則決定：
				if (u < 0)
					// 日全食
					// magnitude > 1;
					feature.type = 'total';
				else if (u > 0.0047)
					// 日環食
					// magnitude < 1;
					feature.type = 'annular';
				else {
					var ω = 0.00464 * Math.sqrt(1 - γ * γ);
					if (u < ω)
						// 日全環食 Hybrid, annular-total
						feature.type = 'hybrid';
					else
						// 日環食
						// magnitude < 1;
						feature.type = 'annular';
				}

			} else if (abs_γ < 1.5433 + u) {
				// 則沒有日食中心，是一個部分食。日偏食
				feature.type = 'partial';
				if (abs_γ < 1.0260) {
					// 影錐的一部分可能觸及地表(在地球兩極地區)，而錐軸則沒有碰到地球。
				} else {
					// 沒有日食中心的全食或環食(因錐軸不經過地表，所以沒有中心)，是一個部分食。
				}
				// 在部分食的情況下，最大食發生在地表上距離影軸最近的那個點。在該點，食的程度(譯者注：大概指食分吧)是：
				// p. 382. (54.2)
				feature.magnitude = (1.5433 + u - abs_γ) / (0.5461 + 2 * u);
			} else {
				// 在地表上看不到日食。
				// no eclipse is visible from the Earth's surface.
			}

		} else {
			// 月食, parse === 2
			var semiduration_c,
			// penumbra 半影在月亮上的半徑，單位是地球直徑
			ρ = 1.2848 + u,
			// umbra 本影在月亮上的半徑，單位是地球直徑
			σ = 0.7403 - u,
			// p. 382. (54.4) 本影 umbral eclipses
			magnitude = (1.0128 - u - abs_γ) / 0.5450;
			if (magnitude >= 1) {
				feature.type = 'total';
				semiduration_c = 0.4678 - u;
			} else if (magnitude > 0) {
				feature.type = 'partial';
				semiduration_c = 1.0128 - u;
			} else {
				// p. 382. (54.3) 半影 penumbral eclipses
				magnitude = (1.5573 + u - abs_γ) / 0.545;
				if (magnitude > 0) {
					// 應注意，大部分半影月食(月亮僅進入地球半影)不能人眼分辨出來。
					feature.type = 'penumbral';
					semiduration_c = 1.5573 + u;
				} else {
					// 如食分為負值，說明沒有月食。
				}
			}
			if (semiduration_c > 0) {
				feature.magnitude = magnitude;
				// 計算半持續時間，單位是分鐘：
				feature.semiduration = 60 * Math.sqrt(
				// semidurations of the partial and total phases
				semiduration_c * semiduration_c - γ * γ)
						/ (0.5458 + 0.0400 * Math.cos(Mm));
			}
		}

		if (feature.type) {
			feature.object = phase === 0 ? 'solar' : 'lunar';
			// the time of maximum eclipse, 食甚時間.
			feature.TT = TT_JD + ΔJD;
		}

		// assert: typeof new Number(TT_JD) === "object";
		// Object.prototype.toString.call(new Number(TT_JD)) ===
		// "[object Number]"
		TT_JD = Object.assign(new Number(TT_JD), {
			M : normalize_radians(M),
			// M′
			Mm : normalize_radians(Mm),
			F : F,
			Ω : normalize_radians(Ω),
			E : E,
			P : P
		}, feature);
		return TT_JD;
	}

	_.mean_lunar_phase = mean_lunar_phase;

	/**
	 * 超過此角度則不會發生日蝕。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Explanatory Supplement to the Astronomical Ephemeris. Third impression
	 * 1974.<br />
	 * p. 215.<br />
	 * 
	 * @type {Number} in radians
	 * @inner
	 */
	var solar_eclipse_limit = degrees_to_radians(1, 34, 46),
	/**
	 * 超過此角度則不會發生月蝕。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Explanatory Supplement to the Astronomical Ephemeris. Third impression
	 * 1974.<br />
	 * p. 258.<br />
	 * 
	 * @type {Number} in radians
	 * @inner
	 */
	lunar_eclipse_limit = degrees_to_radians(1, 26, 19);

	/**
	 * the ellipticity of the Earth's spheroid. e^2 = 0.00669454 for 1968
	 * onwards<br />
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Explanatory Supplement to the Astronomical Ephemeris. Third impression
	 * 1974.<br />
	 * p. 223.
	 * 
	 * For Hayford's spheroid (flattening 1/297) the coefficient (1 -
	 * e^2)^(-1/2) is equal to 1.003378.
	 * 
	 * @see https://en.wikipedia.org/wiki/Flattening
	 */
	var eccentricity_square
	//
	= (2 - TERRA_FLATTENING) * TERRA_FLATTENING,
	// For 1968 onwards:
	// Lunar Radius Constants (Penumbra)
	Lunar_Radius_k1 = 0.272488,
	// Lunar Radius Constants (Umbra)
	Lunar_Radius_k2 = 0.272281;

	/**
	 * 取得 TT_JD 時的 Besselian Elements 日月食資訊。<br />
	 * not yet done
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Explanatory Supplement to the Astronomical Ephemeris. Third impression
	 * 1974.<br />
	 * p. 219.<br />
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Array}local [
	 *            latitude (°), longitude (°), time zone (e.g., UTC+8: 8),
	 *            elevation or geometric height (m) ]
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 * 
	 * @returns {Object}Besselian Elements
	 */
	function Besselian_elements(TT_JD, local, options) {
		// 前置處理。
		if (!library_namespace.is_Object(options)) {
			if (!options && library_namespace.is_Object(local)) {
				options = local;
				// 這邊預設採用 0,0 是為了計算 .π，但此法不見得理想!
				local = options.local || [ 0, 0 ];
			} else
				options = Object.create(null);
		}

		var sun_coordinates = solar_coordinates(TT_JD, {
			equatorial : true,
			local : local
		}), moon_coordinates = lunar_coordinates(TT_JD, {
			equatorial : true,
			local : local
		});

		// adapt p. 219.
		if (false) {
			if (options.get_diff)
				return {};
			moon_coordinates.α
			//
			= degrees_to_radians(328, 13, 44.29);
			moon_coordinates.δ
			//
			= degrees_to_radians(-11, 53, 31.83);
			sun_coordinates.α
			//
			= degrees_to_radians(328, 38, 50.42);
			sun_coordinates.δ
			//
			= degrees_to_radians(-12, 42, 49.04);
			moon_coordinates.π
			//
			= degrees_to_radians(0, 61, 5.814);
			sun_coordinates.Δ = 0.9878805;
			Lunar_Radius_k1 = Lunar_Radius_k2 = 0.272274;
			sun_coordinates.LHA
			//
			= degrees_to_radians(296, 26, 22.3);
		}

		// p. 215.
		/**
		 * β☾: the latitude of the Moon at the time of conjunction in longitude
		 */
		var βm = moon_coordinates.π - sun_coordinates.π
				+ (semidiameter(moon_coordinates, MOON_NAME)
				//
				- semidiameter(sun_coordinates, SUN_NAME))
				* ARCSECONDS_TO_RADIANS;

		// TODO: test solar_eclipse_limit, lunar_eclipse_limit.

		// p. 216.
		var b = Math.sin(sun_coordinates.π) / Math.sin(moon_coordinates.π),
		// cos(α☉)
		cos_αs = Math.cos(sun_coordinates.α),
		// cos(δ☉)
		cos_δs = Math.cos(sun_coordinates.δ),
		// cos(α☾)
		cos_αm = Math.cos(moon_coordinates.α),
		// cos(δ☾)
		cos_δm = Math.cos(moon_coordinates.δ),
		// sin(δ☾)
		sin_δm = Math.sin(moon_coordinates.δ),

		/**
		 * a and d designate the right ascension and declination of the point Z
		 * on the celestial sphere towards which the axis of the shadow is
		 * directed
		 */
		/** g*cos(d)*cos(a) */
		g_cos_d_cos_a = cos_δs * cos_αs - b * cos_δm * cos_αm,
		/** g*cos(d)*sin(a) */
		g_cos_d_sin_a = cos_δs * Math.sin(sun_coordinates.α) - b * cos_δm
				* Math.sin(moon_coordinates.α),
		/** g*cos(d) */
		g_cos_d = Math.sqrt(g_cos_d_cos_a * g_cos_d_cos_a + g_cos_d_sin_a
				* g_cos_d_sin_a),
		/** g*sin(d) */
		g_sin_d = Math.sin(sun_coordinates.δ) - b * sin_δm,
		/** g=G/R */
		g = Math.sqrt(g_cos_d * g_cos_d + g_sin_d * g_sin_d),

		sin_d = g_sin_d / g, cos_d = Math.sqrt(1 - sin_d * sin_d),
		//
		tan_a = g_cos_d_sin_a / g_cos_d_cos_a,
		// a 與 α☉=sun_coordinates.α 有差距 (p. 219.)
		a = Math.atan(tan_a),

		// p. 217.
		/** sin(π☾) */
		sin_πm = Math.sin(moon_coordinates.π),
		/** cos(α☾-a) */
		cos_αmma = Math.cos(moon_coordinates.α - a),
		// 月球於地球上之 rectangular coordinates (直角座標)投影。
		// fundamental plane (基準平面)之 z 軸對準太陽。x 軸對準地球赤道。y 軸向北。
		// [x,y,z] unit: Earth equatorial radius
		x = cos_δm * Math.sin(moon_coordinates.α - a) / sin_πm,
		//
		y = (sin_δm * cos_d - cos_δm * sin_d * cos_αmma) / sin_πm;

		var z = (sin_δm * sin_d + cos_δm * cos_d * cos_αmma) / sin_πm;

		// var R = sun_coordinates.Δ;
		var tmp = g * sun_coordinates.Δ;
		// NG
		if (false) {
			sin_f1 = (Math.sin(sun_coordinates.semidiameter
					* ARCSECONDS_TO_RADIANS) + Lunar_Radius_k1
					* Math.sin(sun_coordinates.π))
					/ tmp;
			sin_f2 = (Math.sin(sun_coordinates.semidiameter
					* ARCSECONDS_TO_RADIANS) - Lunar_Radius_k2
					* Math.sin(sun_coordinates.π))
					/ tmp;
		}
		/**
		 * The angles f1, f2 which the generators of the penumbral (subscript 1)
		 * and umbral (subscript 2)<br />
		 * For 1968 onwards:
		 */
		var sin_f1 = 0.004664018 / tmp,
		//
		sin_f2 = 0.004640792 / tmp,

		/**
		 * p. 218.<br />
		 * distances of the vertices of the penumbral and umbral cones above the
		 * fundamental plane are thus, in units of the equatorial radius of the
		 * Earth:
		 */
		c1 = z + Lunar_Radius_k1 / sin_f1,
		//
		c2 = z - Lunar_Radius_k2 / sin_f2,

		tan_f1 = sin_f1 / Math.sqrt(1 - sin_f1 * sin_f1),
		//
		tan_f2 = sin_f2 / Math.sqrt(1 - sin_f2 * sin_f2),
		/**
		 * l1,l2: the radii of the penumbra and umbra on the fundamental plane
		 */
		l1 = c1 * tan_f1,
		// p. 239.
		// 0.5464: mean value of l1 - l2 adopted from 1963 onwards.
		// l2 = c2 * tan_f2 || (l1 - 0.5464),
		l2 = c2 * tan_f2;

		if (false) {
			console.log(format_radians(
			//
			normalize_radians(sun_coordinates.LHA)));
			console.log(normalize_radians(sun_coordinates.LHA)
					/ DEGREES_TO_RADIANS);
		}
		// p. 217.
		// ephemeris hour angle = ephemeris sidereal time - a
		// μ = Greenwich視恆星時"Apparent sidereal time" − 地心赤經a
		var μ = GAST(TT_of(TT_JD, true), TT_JD) - a;
		// console.log('μ=' + format_radians(normalize_radians(μ)));

		if (options.get_diff)
			return {
				x : x,
				y : y,
				z : z,
				c1 : c1,
				c2 : c2,
				l1 : l1,
				l2 : l2,
				μ : μ,
				sin_d : sin_d
			};

		var elements_1_hour = Besselian_elements(TT_JD + 1 / ONE_DAY_HOURS,
				local, {
					get_diff : true
				});
		// console.log(elements_1_hour);

		// p. 219.
		var
		// μ′, hourly variations
		// μp/DEGREES_TO_RADIANS
		μp = elements_1_hour.μ - μ,
		// d′
		dp = Math.asin(elements_1_hour.sin_d) - Math.asin(sin_d);
		// console.log("μ′=" + μp + ", d′=" + dp);

		var
		// p. 220.
		/**
		 * It is always sufficient to calculate them for the integral hour
		 * nearest conjunction
		 */
		ρ1 = Math.sqrt(1 - eccentricity_square * cos_d * cos_d),
		//
		ρ2 = Math.sqrt(1 - eccentricity_square * sin_d * sin_d);

		var
		// p. 220.
		sin_d1 = sin_d / ρ1,
		//
		cos_d1 = Math.sqrt(1 - eccentricity_square) * cos_d / ρ1,

		/** sin(d1-d2) */
		sin_d1md2 = eccentricity_square * sin_d * cos_d / ρ1 / ρ2,
		/** cos(d1-d2) */
		cos_d1md2 = Math.sqrt(1 - eccentricity_square) / ρ1 / ρ2;

		var
		// x′
		xp = elements_1_hour.x - x,
		// y′
		yp = elements_1_hour.y - y,
		// z′
		zp = elements_1_hour.z - z,
		// c2′
		c2p = elements_1_hour.c2 - c2;

		// p. 223.
		/**
		 * Central line of total or annular phase
		 */
		var central = {
			ξ : x,
			η : y,
			η1 : y / ρ1
		};
		tmp = 1 - x * x - central.η1 * central.η1;
		if (tmp >= 0) {
			central.ζ1 = Math.sqrt(tmp);
			// central.s = central.L2 / n;
			central.ζ = ρ2 * (
			//
			central.ζ1 * cos_d1md2 - central.η1 * sin_d1md2);
			// ξ′
			central.ξp = μp * (-y * sin_d + central.ζ * cos_d);
			// η′
			central.ηp = μp * x * sin_d - dp * central.ζ;
			tmp = xp - central.ξp;
			central.n = Math.sqrt(tmp * tmp + (yp - central.ηp)
					* (yp - central.ηp));
			central.L1 = l1 - central.ζ * tan_f1;
			central.L2 = l2 - central.ζ * tan_f2;
			central.magnitude = (central.L1 - central.L2)
					/ (central.L1 + central.L2);
			central.s = Math.abs(central.L2) / central.n;
			central.duration = central.s * 60 * 60 * 2;
			// p. 223.
			central.θ = Math
					.atan(x, -central.η1 * sin_d1 + central.ζ1 * cos_d1);
			central.λ = μ - central.θ;
			central.longitude = from_ephemeris_longitude(central.λ, TT_JD);
			// sin(φ1)
			tmp = central.η1 * cos_d1 + central.ζ1 * sin_d1;
			central.φ = format_radians(normalize_radians(tmp
			//
			/ Math.sqrt(1 - tmp * tmp) / Math.sqrt(1 - eccentricity_square),
					true), 'decimal');
		} else {
			// 超過了地球的半徑，無日月蝕。
			central.ζ2 = tmp;
		}
		if (options.get_central)
			return central;

		// p. 219.
		// p. 223.
		var
		// θ is the local hour angle of the axis of shadow.
		// θ = LHA = μ - ephemeris longitude λ*
		// a 與 sun_coordinates.α 有差距，因此重算，不用 sun_coordinates.LHA。
		θ = μ - to_ephemeris_longitude(local[1], TT_JD),
		//
		sin_θ = Math.sin(θ), cos_θ = Math.sqrt(1 - sin_θ * sin_θ);
		// console.log('θ=' + format_radians(normalize_radians(θ)));

		// p. 220.
		/** the geodetic latitude of a point on the Earth's surface */
		var φ = local[0] * DEGREES_TO_RADIANS, sin_φ = Math.sin(φ),
		//
		C = 1 / Math.sqrt(1 - eccentricity_square * sin_φ * sin_φ),
		//
		S = (1 - eccentricity_square) * C,
		// p. 241.
		H = (local[3] || 0) * 0.1567850e-6,
		// φ′: geocentric latitude of φ
		ρsin_φp = (S + H) * sin_φ, ρcos_φp = (C + H) * Math.cos(φ),
		//
		sin_φ1 = ρsin_φp / Math.sqrt(1 - eccentricity_square),
		//
		cos_φ1 = ρcos_φp;
		// ((sin_φ1*sin_φ1+cos_φ1*cos_φ1)) should be 1

		// p. 219.
		// ephemeris longitude λ*, geocentric latitude φ′, at a distance
		// ρ from the centre of the terrestrial spheroid
		// [ξ,η,ζ] unit: Earth equatorial radius
		var ξ = ρcos_φp * sin_θ,
		//
		η = ρsin_φp * cos_d - ρcos_φp * sin_d * cos_θ,
		//
		ζ = ρsin_φp * sin_d + ρcos_φp * cos_d * cos_θ;

		var η1 = sin_φ1 * cos_d1 - cos_φ1 * sin_d1 * cos_θ,
		//
		ζ1 = sin_φ1 * sin_d1 + cos_φ1 * cos_d1 * cos_θ;

		// p. 221.
		// Auxiliary elements of an eclipse
		/**
		 * Q: the position angle (measured eastwards from the north, i.e. from
		 * the y-axis towards the x-axis) of the axis from the observer
		 */

		var
		/**
		 * At a height ζ above the fundamental plane the radius L of the shadow
		 * is given by: L = l - ζ * tan(f)
		 */
		// penumbra
		L1 = l1 - ζ * tan_f1,
		// umbra
		L2 = l2 - ζ * tan_f2;

		var
		// p. 222.
		l1p = elements_1_hour.l1 - l1,
		//
		l2p = elements_1_hour.l2 - l2,
		// a1′
		a1p = -l1p - μp * x * tan_f1 * cos_d,
		// a2′
		a2p = -l2p - μp * x * tan_f2 * cos_d,
		// b′
		bp = -yp + μp * x * sin_d,
		// c1′
		c1p = xp + μp * y * sin_d + μp * l1 * tan_f1 * cos_d,
		// c2′
		c2p = xp + μp * y * sin_d + μp * l2 * tan_f2 * cos_d,

		// p. 224.
		// ξ′= μp * (y*sin_d + ζ*cos_d)
		ξp = μp * cos_φ1 * cos_θ,
		// η′
		ηp = μp * x * sin_d - dp * ζ,
		// p. 223.
		/** speed of the shadow relative to the observer */
		n = Math.sqrt((xp - ξp) * (xp - ξp) + (yp - ηp) * (yp - ηp)),
		/**
		 * semi-duration s of the total, or annular, phase on the central line
		 */
		s = Math.abs(L2) / n,
		// duration: hour (semi-duration) to seconds
		duration = s * 60 * 60 * 2,

		// p. 224.
		// tan Qo is required in example 9.7
		tan_Q0 = (ηp - yp) / (xp - ξp);

		// p. 224.
		// Northern and southern limits of umbra and penumbra
		function get_limit(southern, penumbra) {
			var ap, cp, l, tan_f;
			if (penumbra)
				ap = a1p, cp = c1p, l = l1, tan_f = tan_f2;
			else
				// umbra
				ap = a2p, cp = c2p, l = l2, tan_f = tan_f2;
			/**
			 * p. 225.<br />
			 * If the latter is not available, as for example in the case of
			 * non-central eclipses, it is sufficient to set: _ζ = 0
			 */
			var _ζ = ζ || 0, cos_Q = 1;
			var _ξ, last_ζ;
			do {
				// 高
				var adjacent = bp - _ζ * dp - ap / cos_Q;
				// 底邊
				var opposite = cp - _ζ * μp * cos_d;
				// 斜邊
				var hypotenuse = Math.sqrt(adjacent * adjacent + opposite
						* opposite);
				// var Q = Math.atan2(bp, (cp - _ζ * μp * cos_d));

				cos_Q = opposite / hypotenuse;
				/**
				 * The sign of cos Q is positive for the northern limit of a
				 * total eclipse and the southern limit of an annular eclipse;
				 * it is negative for the southern limit of a total eclipse and
				 * the northern limit of an annular eclipse.
				 */
				if (southern ^ penumbra ^ (cos_Q < 0))
					hypotenuse = -hypotenuse, cos_Q = -cos_Q;

				var _L = l - _ζ * tan_f;
				// var _ξ = x - _L * Math.sin(Q);
				_ξ = x - _L * bp / hypotenuse;
				var _η1 = (y - _L * cos_Q) / ρ1;

				// warning: 對於northern penumbra，可能有 |_ξ|>=1 &&
				// |_η1|>=1，表示不在範圍內?
				var _ζ1 = Math.sqrt(1 - _ξ * _ξ - _η1 * _η1);
				last_ζ = _ζ;
				_ζ = ρ2 * (_ζ1 * cos_d1md2 - _η1 * sin_d1md2);
				// console.log([ _ζ, _ζ - last_ζ ]);
			} while (Math.abs(_ζ - last_ζ) > Number.EPSILON);

			// p. 223.
			var Q = Math.acos(cos_Q);
			var sin_θ = _ξ / cos_φ1, θ = Math.asin(sin_θ);
			// λ*: ephemeris longitude 星曆經度
			var λ = μ - θ;

			var _sin_φ1 = _η1 * cos_d1 + _ζ1 * sin_d1,
			//
			_cos_φ1 = (-_η1 * sin_d1 + _ζ1 * cos_d1) / Math.cos(θ),
			//
			φ = Math.atan(_sin_φ1 / _cos_φ1
					/ Math.sqrt(1 - eccentricity_square));
			return isNaN(φ) ? null : [
					format_radians(normalize_radians(λ), 'decimal'),
					format_radians(normalize_radians(φ, true), 'decimal') ];
		}

		var northern_limit = get_limit(),
		//
		southern_limit = get_limit(true);
		var northern_penumbra_limit = get_limit(false, true);
		var southern_penumbra_limit = get_limit(true, true);

		// p. 228.
		// Outline curves
		var m = Math.sqrt(x * x + y * y),
		// in radians
		M = Math.atan(x / y),
		//
		QmM = Math.acos((m * m + l1 * l1 - 1) / 2 / l1 / m);

		// p. 228.
		// using the mean the same as get_limit()
		// test for Q = 0°
		var c_Q = 0,
		//
		c_ξ = x - L1 * Math.sin(c_Q),
		//
		c_η1 = (y - L1 * Math.cos(c_Q)) / ρ1,
		// ξ^2
		c_ξ2 = 1 - c_ξ * c_ξ - c_η1 * c_η1;

		/**
		 * If the angle (Q - M) is imaginary, there are no end points to the
		 * curve, and the angle Q takes all values from 0° to 360°.
		 */
		var outline = [ format_radians(normalize_radians(M - QmM), 'decimal'),
				format_radians(normalize_radians(M + QmM), 'decimal')
		//
		];
		// console.log(c_ξ2 + ', [' + outline + ']');
		if ((c_ξ2 > 0) ^ (outline[0] > outline[1]))
			// swap.
			outline = [ outline[1], outline[0] ];

		// outline = [30,200]: 200°~360°, 0°~30°

		// TODO: p. 229.

		return {
			βm : βm,
			d : Math.asin(sin_d),
			μ : μ,
			θ : θ,
			φ : φ,
			l1 : l1,
			l1p : l1p,
			l2 : l2,
			l2p : l2p,
			central : central,
			ζ : ζ,
			c1 : c1,
			c2 : c2,
			L1 : L1,
			L2 : L2,
			// p. 246.
			magnitude : (L1 - L2) / (L1 + L2),
			// Central Duration
			duration : duration,
			x : x,
			xp : xp,
			y : y,
			yp : yp,
			z : z,
			zp : zp,
			tan_Q0 : tan_Q0,
			// 4 items in degrees
			northern_limit : northern_limit,
			southern_limit : southern_limit,
			northern_penumbra_limit : northern_penumbra_limit,
			southern_penumbra_limit : southern_penumbra_limit,
			// in degrees
			outline : outline
		};
	}

	_.Besselian_elements = Besselian_elements;

	Besselian_elements.lunar = function(TT_JD, options) {
		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var local = options.local || [ 0, 0 ];

		var sun_coordinates = solar_coordinates(TT_JD, {
			equatorial : true,
			local : local
		}), moon_coordinates = lunar_coordinates(TT_JD, {
			equatorial : true,
			local : local
		});

		// p. 258.
		var a = sun_coordinates.α + TURN_TO_RADIANS / 2,
		//
		d = -sun_coordinates.δ,
		// p. 260.
		// Corrections to position of the Moon
		// α☾
		αm = moon_coordinates.α - 0.20 * ARCSECONDS_TO_RADIANS,
		// δ☾
		δm = moon_coordinates.δ - 0.46 * ARCSECONDS_TO_RADIANS;

		var b = Math.sin(sun_coordinates.π) / Math.sin(moon_coordinates.π),
		// cos(α☉)
		cos_αs = Math.cos(a),
		// cos(δ☉)
		cos_δs = Math.cos(d),
		// cos(α☾)
		cos_αm = Math.cos(moon_coordinates.α),
		// cos(δ☾)
		cos_δm = Math.cos(moon_coordinates.δ),
		// sin(δ☾)
		sin_δm = Math.sin(moon_coordinates.δ),

		/**
		 * a and d designate the right ascension and declination of the point Z
		 * on the celestial sphere towards which the axis of the shadow is
		 * directed
		 */
		/** g*cos(d)*cos(a) */
		g_cos_d_cos_a = cos_δs * cos_αs - b * cos_δm * cos_αm,
		/** g*cos(d)*sin(a) */
		g_cos_d_sin_a = cos_δs * Math.sin(a) - b * cos_δm
				* Math.sin(moon_coordinates.α),
		/** g*cos(d) */
		g_cos_d = Math.sqrt(g_cos_d_cos_a * g_cos_d_cos_a + g_cos_d_sin_a
				* g_cos_d_sin_a),
		/** g*sin(d) */
		g_sin_d = Math.sin(d) - b * sin_δm,
		/** g=G/R */
		g = Math.sqrt(g_cos_d * g_cos_d + g_sin_d * g_sin_d),

		sin_d = g_sin_d / g, cos_d = Math.sqrt(1 - sin_d * sin_d),
		//
		tan_a = g_cos_d_sin_a / g_cos_d_cos_a,

		/** cos(α☾-a) */
		cos_αmma = Math.cos(moon_coordinates.α - a),
		//
		x = cos_δm * Math.sin(moon_coordinates.α - a),
		//
		y = (sin_δm * cos_d - cos_δm * sin_d * cos_αmma);

		if (options.get_diff)
			return {
				x : x,
				y : y
			};

		var elements_1_hour = Besselian_elements.lunar(TT_JD + 1
				/ ONE_DAY_HOURS, {
			get_diff : true
		});

		var
		// x′
		xp = elements_1_hour.x - x,
		// y′
		yp = elements_1_hour.y - y;

		/** n^2 */
		var n2 = xp * xp + yp * yp,
		//
		n = Math.sqrt(n2),
		//
		t = -(x * xp + y * yp) / n2;

		// the correction t to a starting time To to obtain the time of
		// greatest obscuration is determined by solving:
		var tmp = TT_JD + t / ONE_DAY_HOURS;
		if (options.no_iterate && TT_JD !== tmp)
			return Besselian_elements.lunar(tmp, options);
		TT_JD = tmp;

		var Δ = Math.abs(x * yp - y * xp) / n;

		// p. 257.
		/**
		 * 
		 * Reference 資料來源/資料依據:<br />
		 * NASA - Enlargement of Earth's Shadows
		 * 
		 * @see http://eclipse.gsfc.nasa.gov/LEcat5/shadow.html
		 */
		// 1.01 ≅ 1 + 1/85 - 1/594.
		tmp = 1.01 * moon_coordinates.π + sun_coordinates.π;
		/** s☉: semi-diameter of the Sun */
		var ss = semidiameter(sun_coordinates, SUN_NAME)
				* ARCSECONDS_TO_RADIANS,
		/** s☾: semi-diameter of the Moon */
		sm = semidiameter(moon_coordinates, MOON_NAME) * ARCSECONDS_TO_RADIANS,
		// penumbral radius
		f1 = tmp + ss,
		// umbral radius
		f2 = tmp - ss,
		// angular distance (L) between the centres of the Moon and the
		// shadow
		// at beginning and end of the penumbral eclipse
		L1 = f1 + sm,
		// at beginning and end of the partial eclipse
		L2 = f2 + sm,
		// at beginning and end of the total eclipse
		L3 = f2 - sm;

		// p. 259.
		/** Δ^2 */
		var Δ2 = Δ * Δ, type,
		// semi-duration in hours
		semi_duration = [];
		tmp = L1 * L1 - Δ2;
		if (tmp < 0) {
			// no eclipse
			// return;
			// ** DO NOT set type here!
		} else {
			semi_duration.push(Math.sqrt(tmp) / n);
			tmp = L2 * L2 - Δ2;
			if (tmp < 0)
				// penumbral eclipse
				type = 'penumbral';
			else {
				semi_duration.push(Math.sqrt(tmp) / n);
				tmp = L3 * L3 - Δ2;
				if (tmp < 0)
					type = 'partial';
				else {
					semi_duration.push(Math.sqrt(tmp) / n);
					type = 'total';
				}
			}
		}

		/** L^2 */
		tmp = (x + xp * t) * (x + xp * t)
		//
		+ (y + yp * t) * (y + yp * t);
		var L = Math.sqrt(tmp),
		/** L^2 - Δ^2 */
		L1mΔ2 = tmp - Δ2;

		/**
		 * angular distance between the centres of the Moon and the shadow
		 */
		var m = Math.sqrt(x * x + y * y);

		return {
			TT : TT_JD,
			semi_duration : semi_duration,
			// f1 : normalize_radians(f1) / ARCSECONDS_TO_RADIANS,
			// f2 : normalize_radians(f2) / ARCSECONDS_TO_RADIANS,
			// L1 : normalize_radians(L1) / ARCSECONDS_TO_RADIANS,
			// L2 : normalize_radians(L2) / ARCSECONDS_TO_RADIANS,
			// L3 : normalize_radians(L3) / ARCSECONDS_TO_RADIANS,
			// Δ : normalize_radians(Δ) / ARCSECONDS_TO_RADIANS,
			type : type,
			// The values of L, m, and s☉ should be those corresponding
			// to the time of greatest obscuration.
			magnitude : (L2 - m) / 2 / sm,
			penumbral_magnitude : (L1 - m) / 2 / sm,
			/**
			 * The latitudes (φ) and ephemeris longitudes (λ*) of the places
			 * that have the Moon in the zenith at given times
			 */
			latitude : format_radians(normalize_radians(moon_coordinates.δ,
					true), 'decimal'),
			// ephemeris sidereal time - α☾
			longitude : from_ephemeris_longitude(
					GAST(TT_of(TT_JD, true), TT_JD) - moon_coordinates.α, TT_JD)
		};
	};

	/**
	 * 取得 TT_JD 時的日月食資訊。
	 * 
	 * 中國古代天象記錄總表 http://chungfamily.woweb.net/zbxe/board_013/6819
	 * http://mdonchan.web.fc2.com/siryou/toita/jissoku-1.htm
	 * 
	 * @param {Number}TT_JD
	 *            Julian date (JD of 天文計算用時間 TT)
	 * @param {Integer}phase
	 *            0:朔0°, 1:上弦90°, 2:望180°, 3:下弦270°
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 * 
	 * @returns {Object}日月食資訊。
	 */
	function eclipse_JD(TT_JD, phase, options) {
		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);
		if (!options.eclipse)
			options = Object.assign({
				eclipse : true
			}, options);

		var year_month = options.year ? TT_JD
				: Julian_century(TT_JD) * 100 + 2000;

		/**
		 * 日月食資訊。
		 * 
		 * @type {Object}
		 */
		var eclipse_data
		//
		= mean_lunar_phase(year_month, phase, options);

		if (eclipse_data.type) {
			eclipse_data.name
			// gettext_config:{"id":"total-solar-eclipse","mark_type":"combination_message_id"}
			// gettext_config:{"id":"annular-solar-eclipse","mark_type":"combination_message_id"}
			// gettext_config:{"id":"hybrid-solar-eclipse","mark_type":"combination_message_id"}
			// gettext_config:{"id":"partial-solar-eclipse","mark_type":"combination_message_id"}
			// gettext_config:{"id":"total-lunar-eclipse","mark_type":"combination_message_id"}
			// gettext_config:{"id":"partial-lunar-eclipse","mark_type":"combination_message_id"}
			// gettext_config:{"id":"penumbral-lunar-eclipse","mark_type":"combination_message_id"}
			= eclipse_data.type + ' ' + eclipse_data.object + ' eclipse';
			eclipse_data.Δlongitude
			// eclipse conjunction 黃經衝 or 合(有相同的黃經)時之月黃緯
			= lunar_coordinates(eclipse_data.TT).β
			//
			/ DEGREES_TO_RADIANS;
			eclipse_data.saros = saros(eclipse_data.TT,
			// push saros series
			phase === 0 ? TYPE_SOLAR : TYPE_LUNAR);

		} else
			eclipse_data = undefined;

		if (eclipse_data && eclipse_data.saros)
			return eclipse_data;

		// ------------------------------------------------------------

		if (!options.elements) {
			var saros_data = saros(TT_JD,
			// push saros series
			phase === 0 ? TYPE_SOLAR : TYPE_LUNAR);

			// 若是有 saros 就當作可能有日月食。
			return saros_data && {
				TT : TT_JD,
				object : phase === 0 ? 'solar' : 'lunar',
				// gettext_config:{"id":"solar-eclipse","mark_type":"combination_message_id"}
				// gettext_config:{"id":"lunar-eclipse","mark_type":"combination_message_id"}
				name : (phase === 0 ? 'solar' : 'lunar') + ' eclipse',
				Δlongitude :
				// eclipse conjunction 黃經衝 or 合(有相同的黃經)時之月黃緯
				lunar_coordinates(TT_JD).β
				//
				/ DEGREES_TO_RADIANS,
				saros : saros_data
			};
		}

		// ------------------------------------------------------------

		// 下面運算頗耗時間。

		if (phase !== 0) {
			eclipse_data = Besselian_elements.lunar(TT_JD)
			if (!eclipse_data.type)
				return;
			var TT = eclipse_data.TT,
			//
			saros_data = saros(TT,
			// push saros series
			phase === 0 ? TYPE_SOLAR : TYPE_LUNAR);

			return Object.assign(eclipse_data, {
				TT : TT,
				object : phase === 0 ? 'solar' : 'lunar',
				// gettext_config:{"id":"total-solar-eclipse","mark_type":"combination_message_id"}
				// gettext_config:{"id":"annular-solar-eclipse","mark_type":"combination_message_id"}
				// gettext_config:{"id":"hybrid-solar-eclipse","mark_type":"combination_message_id"}
				// gettext_config:{"id":"partial-solar-eclipse","mark_type":"combination_message_id"}
				// gettext_config:{"id":"total-lunar-eclipse","mark_type":"combination_message_id"}
				// gettext_config:{"id":"partial-lunar-eclipse","mark_type":"combination_message_id"}
				// gettext_config:{"id":"penumbral-lunar-eclipse","mark_type":"combination_message_id"}
				name : eclipse_data.type + ' '
						+ (phase === 0 ? 'solar' : 'lunar') + ' eclipse',
				Δlongitude :
				// eclipse conjunction 黃經衝 or 合(有相同的黃經)時之月黃緯
				lunar_coordinates(TT).β
				//
				/ DEGREES_TO_RADIANS,
				saros : saros_data
			});
		}

		var get_magnitude = function(TT_JD) {
			var data = Besselian_elements(TT_JD, {
				get_central : true
			}), magnitude = data.magnitude;
			if (isNaN(magnitude))
				// 9: 隨便給，夠大就好。
				// assert: -magnitude < 5 < 9 - data.ζ2
				return 9 - data.ζ2;
			return [ -magnitude, {
				data : data
			} ];
		};

		if (get_magnitude(TT)[0] > 5)
			// 連正中都無值。
			return;

		// using Besselian Elements
		// Explanatory Supplement to the Astronomical Ephemeris. Third
		// impression 1974.
		// p. 211. ECLIPSES AND TRANSITS

		// 朔的時間點日月黃經差為0，距離最大食分應在五分左右，十分內？
		var range = Math.abs(options.range) || .2,
		//
		min_TT = TT_JD - range, max_TT = TT_JD + range;

		if (false) {
			while (isNaN(get_magnitude(min_TT)[0]))
				min_TT += 0.001;
			while (isNaN(get_magnitude(max_TT)[0]))
				max_TT -= 0.001;
		}

		// 發生此日月食，時甚時之實際 TT in JD.
		var TT = library_namespace.find_minima(
		//
		get_magnitude, min_TT, max_TT);

		if (TT.y > 5)
			return;

		var saros_data = saros(TT,
		// push saros series
		phase === 0 ? TYPE_SOLAR : TYPE_LUNAR);

		return Object.assign(TT.data, {
			TT : TT,
			object : phase === 0 ? 'solar' : 'lunar',
			// gettext_config:{"id":"solar-eclipse","mark_type":"combination_message_id"}
			// gettext_config:{"id":"lunar-eclipse","mark_type":"combination_message_id"}
			name : (phase === 0 ? 'solar' : 'lunar') + ' eclipse',
			Δlongitude :
			// eclipse conjunction 黃經衝 or 合(有相同的黃經)時之月黃緯
			lunar_coordinates(TT).β
			//
			/ DEGREES_TO_RADIANS,
			saros : saros_data
		});

		// ------------------------------------------------------------

		// 以下方法無依據。這樣的條件也有可能過疏過密？

		var
		/**
		 * eclipse conjunction 黃經衝 or 合(有相同的黃經)時之日月角距離 (in arcseconds)。
		 * 
		 * TT.y≈Math.sqrt((TT.s.λ-TT.l.λ)*(TT.s.λ-TT.l.λ)+(TT.s.β-TT.l.β)*(TT.s.β-TT.l.β))
		 * 
		 * @type {Number} in arcseconds
		 */
		distance = TT.y / ARCSECONDS_TO_RADIANS,
		/**
		 * 日面的地心視半徑 (in arcseconds)。Geocentric semi-diameter of the Sun.
		 * 
		 * @type {Number} in arcseconds
		 */
		sun_radius = semidiameter(TT.s, SUN_NAME),
		/**
		 * 月面的地心視半徑 (in arcseconds)。
		 * 
		 * @type {Number} in arcseconds
		 */
		moon_radius = semidiameter(TT.l, MOON_NAME),
		/**
		 * 食甚食分 magnitude 角距離 (in arcseconds)。
		 * 
		 * @type {Number} in arcseconds
		 */
		magnitude = sun_radius + moon_radius - distance;

		// ((magnitude < 0))在魯隱公1年4月1日(-722/4/14)會漏掉!!
		if (false && magnitude < 0 && !saros_data)
			// 無遮掩??
			return;

		// β☾
		var βm = TT.l.π - TT.s.π + (moon_radius - sun_radius)
				* ARCSECONDS_TO_RADIANS;
		if (βm > phase === 0 ? solar_eclipse_limit : lunar_eclipse_limit)
			return;

		magnitude /= phase === 0 ? sun_radius : moon_radius;

		eclipse_data = {
			TT : TT,
			object : phase === 0 ? 'solar' : 'lunar',
			// gettext_config:{"id":"solar-eclipse","mark_type":"combination_message_id"}
			// gettext_config:{"id":"lunar-eclipse","mark_type":"combination_message_id"}
			name : (phase === 0 ? 'solar' : 'lunar') + ' eclipse',
			Δlongitude :
			// eclipse conjunction 黃經衝 or 合(有相同的黃經)時之月黃緯
			lunar_coordinates(TT).β
			//
			/ DEGREES_TO_RADIANS,
			saros : saros_data
		};

		if (magnitude > 0)
			eclipse_data.magnitude = magnitude;

		return eclipse_data;

		// ------------------------------------------------------------
		// old

		/**
		 * local (地面某點) 觀測者緯度 latitude (度)。
		 * 
		 * @type {Number}
		 */
		var latitude =
		//
		Array.isArray(options.local) ? options.local[0]
		//
		: options.latitude || 45,
		// 朔的時間點日月黃經差為0，距離最大食分應在五分左右，十分內？
		/**
		 * 計算月亮(月心)的緯度→與黃道距離(度)。
		 * 
		 * @type {Number}
		 */
		d = lunar_coordinates(TT).β / DEGREES_TO_RADIANS,
		// 計算月面視半徑 (度)。
		/**
		 * 月面的地心視半徑 (度)。
		 * 
		 * TODO: use (coordinates.Δ * AU_TO_METERS) instead of LUNAR_DISTANCE_M
		 * 
		 * @type {Number}
		 */
		r = Math.asin(LUNAR_RADIUS_M / LUNAR_DISTANCE_M)
		// → 以觀測者為中心的座標中看到的月亮視半徑
		* (1 + Math.sin(latitude * DEGREES_TO_RADIANS)
		//
		* TERRA_RADIUS_M / LUNAR_DISTANCE_M)
		// → 度
		/ DEGREES_TO_RADIANS,
		/**
		 * calculate range (度)
		 * 
		 * 初始值: 日面的地心視半徑 (度)。 Geocentric semi-diameter of the Sun
		 * 
		 * @type {Number}
		 */
		range = SOLAR_RADIUS_RADIANS / DEGREES_TO_RADIANS;
		if (phase === 2) {
			// 日食: 計算日面視半徑 (度)。
			// TODO: Besselian elements
		} else {
			// assert: phase === 2
			// 月食: 計算地球本影之半徑, Earth's umbra radius.
			/**
			 * 
			 * Reference 資料來源/資料依據:<br />
			 * NASA - Enlargement of Earth's Shadows
			 * 
			 * @see http://eclipse.gsfc.nasa.gov/LEcat5/shadow.html
			 */

			/**
			 * Equatorial horizontal parallax of the Sun, and 1.01 ≅ 1 + 1/85 -
			 * 1/594. 太陽赤道地平視差 (度)
			 * 
			 * Astronomical Almanac 2011:<br />
			 * Solar parallax, pi_odot:<br />
			 * sin^-1(a_e/A) = 8.794143″
			 * 
			 * @type {Number}
			 * 
			 * @see https://en.wikipedia.org/wiki/Parallax#Solar_parallax
			 */
			var Solar_parallax
			// 1: distance in AU
			= 8.794143 / DEGREES_TO_ARCSECONDS / 1,
			/**
			 * Equatorial horizontal parallax of the Moon 月球赤道地平視差 (度)
			 * 
			 * @type {Number}
			 * 
			 * @see http://farside.ph.utexas.edu/Books/Syntaxis/Almagest/node42.html
			 */
			Lunar_parallax = 41 / DEGREES_TO_ARCSECONDS;
			// http://eclipse.gsfc.nasa.gov/LEcat5/shadow.html
			range = 1.01 * Lunar_parallax + Solar_parallax
			// Geocentric semi-diameter of the Sun
			// 日面的地心視半徑 (度)。
			- range;
			// range: umbral radius 地球本影半徑
		}

		if (eclipse_data = Math.abs(d) < range + r) {
			eclipse_data = {
				TT : TT,
				object : phase === 0 ? 'solar' : 'lunar',
				// gettext_config:{"id":"solar-eclipse","mark_type":"combination_message_id"}
				// gettext_config:{"id":"lunar-eclipse","mark_type":"combination_message_id"}
				name : (phase === 0 ? 'solar' : 'lunar') + ' eclipse',
				Δlongitude :
				// eclipse conjunction 黃經衝 or 合(有相同的黃經)時之月黃緯
				lunar_coordinates(TT_JD).β
				//
				/ DEGREES_TO_RADIANS,
				saros : saros(TT_JD,
				// push saros series
				phase === 0 ? TYPE_SOLAR : TYPE_LUNAR)
			};
		}
		// return maybe has eclipse.
		return eclipse_data;
	}

	_.eclipse_JD = eclipse_JD;

	/**
	 * get JD of lunar phase. Using full LEA-406a or LEA-406b model.
	 * 計算特定月相之時間精準值。可用來計算月相、日月合朔(黑月/新月)、弦、望(滿月，衝)、月食、月齡。
	 * 
	 * @deprecated using accurate_lunar_phase()
	 * 
	 * @param {Number}year_month
	 *            帶小數點的年數，例如1987.25表示1987年3月末。
	 * @param {Integer}phase
	 *            0:朔0°, 1:上弦90°, 2:望180°, 3:下弦270°
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項
	 * 
	 * @returns {Number} Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @see http://koyomi8.com/sub/sunmoon_long.htm
	 * @see http://eco.mtk.nao.ac.jp/cgi-bin/koyomi/cande/phenom_phase.cgi
	 * @see http://homepage3.nifty.com/ayumi_ho/moon1.htm
	 * @see http://www2s.biglobe.ne.jp/~yoss/moon/moon.html
	 * 
	 * @deprecated
	 */
	function deprecated_accurate_lunar_phase
	//
	(year_month, phase, options) {
		var up_degrees, low_degrees,
		// 內插法(線性插值)上下限。
		up_JD, low_JD,
		// 目標角度。
		degrees = phase * 90,
		// 利用平月相的時間，以取得內插法初始近似值。
		TT_JD = mean_lunar_phase(year_month, phase, options),
		// 計算月日視黃經差。
		angle = // options
		//
		// && typeof options.angle === 'function' ? options.angle :
		//
		degrees < 90 ? function(_JD) {
			// window.lunar_count = (window.lunar_count || 0) + 1;
			var d = lunar_phase_angle_of_JD(_JD || TT_JD, true);
			if (d > TURN_TO_DEGREES - 90)
				d -= TURN_TO_DEGREES;
			return d;
		} : function(_JD) {
			return lunar_phase_angle_of_JD(_JD || TT_JD, true);
		},
		// 誤差常於2°之內。
		result_degrees = angle();

		// / 12: 月日視黃經差每日必於 12°–13°之內。
		// 因此每度耗時必小於 1/12 日。此處取最大值。
		if (degrees < result_degrees) {
			// 將 TT_JD 作為上限。
			up_JD = TT_JD, up_degrees = result_degrees;
			// 以 result 反推出一個<b>一定</b>小於目標 TT_JD 之下限。
			low_JD = TT_JD - (result_degrees - degrees) / 12;
			low_degrees = angle(low_JD);
		} else {
			// 將 TT_JD 作為下限。
			low_JD = TT_JD, low_degrees = result_degrees;
			// 以 result 反推出一個<b>一定</b>大於目標 TT_JD 之上限。
			up_JD = TT_JD - (result_degrees - degrees) / 12;
			up_degrees = angle(up_JD);
		}

		library_namespace.debug(
		//
		'初始值: year ' + year_month + ', phase ' + phase
		//
		+ ' (' + degrees + '°): JD' + TT_JD + ' ('
		//
		+ library_namespace.JD_to_Date(UT_of(TT_JD)).format('CE') + '), '
				+ format_degrees(result_degrees) + '; JD: ' + low_JD + '–'
				+ up_JD, 2);

		// 內插法 main loop
		while (low_JD < up_JD) {
			// 估值
			TT_JD = low_JD + (up_JD - low_JD)
			//
			* (degrees - low_degrees) / (up_degrees - low_degrees);
			result_degrees = angle();

			if (result_degrees < degrees) {
				if (low_JD === TT_JD) {
					// 已經得到相當好的效果。
					break;
					// 也可以改變另一項。但效果通常不大，反而浪費時間。
					up_JD = (low_JD + up_JD) / 2;
					up_degrees = angle(up_JD);
				} else {
					low_JD = TT_JD;
					low_degrees = result_degrees;
				}
			} else if (result_degrees > degrees) {
				if (up_JD === TT_JD) {
					// 已經得到相當好的效果。
					break;
					// 也可以改變另一項。但效果通常不大，反而浪費時間。
					low_JD = (low_JD + up_JD) / 2;
					low_degrees = angle(low_JD);
				} else {
					up_JD = TT_JD;
					up_degrees = result_degrees;
				}
			} else
				break;
		}

		library_namespace.debug('JD' + TT_JD + ' ('
		//
		+ library_namespace.JD_to_Date(UT_of(TT_JD)).format('CE')
		//
		+ '): ' + format_degrees(angle(TT_JD)), 2);

		// apply ΔT: TT → UT.
		return options && options.UT ? UT_of(TT_JD) : TT_JD;
	}

	/**
	 * get JD of lunar phase. Using full LEA-406a or LEA-406b model.
	 * 計算特定月相之時間精準值。可用來計算月相、日月合朔(黑月/新月)、弦、望(滿月，衝)、月食、月齡。
	 * 
	 * @param {Number}year_month
	 *            帶小數點的年數，例如1987.25表示1987年3月末。
	 * @param {Integer}phase
	 *            0:朔0°, 1:上弦90°, 2:望180°, 3:下弦270°
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項
	 * 
	 * @returns {Number} Julian date (JD of 天文計算用時間 TT)
	 * 
	 * @see http://koyomi8.com/sub/sunmoon_long.htm
	 * @see http://eco.mtk.nao.ac.jp/cgi-bin/koyomi/cande/phenom_phase.cgi
	 * @see http://homepage3.nifty.com/ayumi_ho/moon1.htm
	 * @see http://www2s.biglobe.ne.jp/~yoss/moon/moon.html
	 */
	function accurate_lunar_phase
	//
	(year_month, phase, options) {
		var
		// 目標角度。
		degrees = phase * 90,
		// 利用平月相的時間，以取得內插法初始近似值。
		TT_JD = mean_lunar_phase(year_month, phase, options),
		// 計算月日視黃經差。
		angle = // options
		//
		// && typeof options.angle === 'function' ? options.angle :
		//
		degrees < 90 ? function(TT_JD) {
			// window.lunar_count = (window.lunar_count || 0) + 1;
			var d = lunar_phase_angle_of_JD(TT_JD, true);
			if (d > TURN_TO_DEGREES - 90)
				d -= TURN_TO_DEGREES;
			return d;
		} : function(TT_JD) {
			return lunar_phase_angle_of_JD(TT_JD, true);
		},
		// 誤差常於2°之內。
		result_degrees = angle(TT_JD);

		TT_JD = library_namespace.find_root(
				'count' in options ? function(TT_JD) {
					options.count++;
					return angle(TT_JD);
				} : angle,
				// / 12: 月日視黃經差每日必於 12°–13°之內。
				// 因此每度耗時必小於 1/12 日。此處取最大值。
				TT_JD - (result_degrees - degrees) / 12, TT_JD, degrees, {
					y1 : result_degrees
				});

		library_namespace.debug(
		//
		'JD' + TT_JD + ' ('
		//
		+ library_namespace.JD_to_Date(UT_of(TT_JD)).format('CE')
		//
		+ '): ' + format_degrees(angle(TT_JD)), 2);

		// apply ΔT: TT → UT.
		return options && options.UT ? UT_of(TT_JD) : TT_JD;
	}

	// phase: 0:朔0°, 1:上弦90°, 2:望180°, 3:下弦270°
	// lunar_phase_cache[year][phase:0–3] = [JD of 日常生活時間 UT, JD, ...]
	var lunar_phase_cache = [];

	/**
	 * get JD of lunar phases. 取得整年之月相。
	 * 
	 * 注意: 中曆2057年9月朔日 為 2057/9/28 UTC+8，與 香港天文台 (
	 * http://www.weather.gov.hk/gts/time/conversionc.htm )、兩千年中西曆轉換 (
	 * http://sinocal.sinica.edu.tw/ ) 不相同。<br />
	 * According to HORIZONS (DE-431), it's about 9/28 19:54 (月亮追過太陽) or 9/29
	 * 00:08 (視角度差最小).
	 * 
	 * 中曆2089年8月朔日 為 2089/9/4 UTC+8，與 兩千年中西曆轉換 不相同。<br />
	 * 中曆2097年7月朔日 為 2097/8/7 UTC+8，與 兩千年中西曆轉換 不相同。<br />
	 * 2000–2100 不合者如上。
	 * 
	 * @param {Number}year
	 *            年數
	 * @param {Integer}phase
	 *            0:朔0°, 1:上弦90°, 2:望180°, 3:下弦270°
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            {Boolean}options.mean: 是否採用平月相。 false: 採用精準值。<br />
	 *            {Integer}options.duration: 取得年數<br />
	 *            {Boolean}options.to_Date: return Date<br />
	 *            {String|Object}options.format: 將 Date 轉成特定 format
	 * 
	 * @returns {Array} [ Julian date (JD of 日常生活時間 UT), JD, ... ]
	 */
	function lunar_phase(year, phase, options) {
		if (year === (year | 0)) {
			if (options === true)
				options = 1;
			if (options > 0 && (options === options | 0))
				// 取得整年之月相。
				options = {
					duration : options
				};
		}
		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var operator, UT_JD;
		if (typeof options.mean === 'boolean')
			operator = options.mean ? mean_lunar_phase : accurate_lunar_phase;
		// whole year
		// options.duration = 1
		// 2 years:
		// options.duration = 2
		if (!options.duration) {
			UT_JD = UT_of((operator || accurate_lunar_phase)(year, phase,
					options));
			return UT_JD;
		}

		var phase_JD = [];

		year |= 0;
		phase |= 0;
		for (var phase_data,
		//
		end = year + options.duration; year < end; year++) {
			// using cache.
			phase_data = lunar_phase_cache[year];
			if (!phase_data)
				// 初始化。
				lunar_phase_cache[year] = phase_data = [];

			if (phase_data = phase_data[phase])
				// has cache. using clone.
				phase_data = phase_data.slice();
			else {
				phase_data = [];
				for (var year_month = year, date, hours;;
				// 0.08: 1 / 12 = .08333333333333
				year_month = Julian_century(TT_of(UT_JD)) * 100 + 2000
				// year_month 加此值以跳到下一個月。
				+ mean_lunar_phase_days / (DAYS_OF_JULIAN_CENTURY / 100)) {
					UT_JD = UT_of((operator || mean_lunar_phase)(year_month,
							phase, options));
					date = library_namespace.JD_to_Date(UT_JD);
					if (!operator
					// auto: 在特別可能有問題的時候採用精準值。
					&& ((hours = date.getHours()) < 2 || hours > 21)) {
						UT_JD = UT_of(accurate_lunar_phase(year_month, phase,
								options));
						date = library_namespace.JD_to_Date(UT_JD);
					}
					date = date.getFullYear();
					if (date === year)
						phase_data.push(UT_JD);
					else if (date - year === 1) {
						phase_data.end = UT_JD;
						// 已經算到次年了。
						break;
					}
				}
				if (options.mean === false)
					lunar_phase_cache[year][phase]
					// using clone.
					= phase_data.slice();
			}

			if (options.to_Date)
				phase_data.forEach(function(UT_JD, index) {
					UT_JD = library_namespace.JD_to_Date(UT_JD);
					if (options.format)
						UT_JD = UT_JD.format(options.format);
					phase_data[index] = UT_JD;
				});
			phase_JD.push(phase_data);
		}

		return options.duration === 1 ? phase_JD[0] : phase_JD;
	}

	_.lunar_phase = lunar_phase;

	/**
	 * get lunar phase of JD. 取得 JD 之月相。
	 * 
	 * @param {Number}UT_JD
	 *            Julian date of local midnight (00:00) (JD of 日常生活時間 UT)
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            {Boolean}options.time: 取得月相時，亦取得時刻。<br />
	 *            {Boolean|String}options.晦: 顯示晦。<br />
	 *            {Boolean}options.index: 顯示 index 而非名稱。<br />
	 *            {Boolean}options.TT: date is TT instead of UT.
	 * 
	 * @returns {Number} phase: 0:朔0°, 1:上弦90°, 2:望180°, 3:下弦270°
	 */
	function lunar_phase_of_JD(UT_JD, options) {
		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var TT_JD;
		if (options.TT)
			UT_JD = UT_of(TT_JD = UT_JD);
		else
			TT_JD = TT_of(UT_JD);

		// 隔日子夜0時剛開始之月相。
		// 90: TURN_TO_DEGREES / 4相 = 360 / 4
		var _phase = lunar_phase_angle_of_JD(TT_JD + 1) / 90;
		if (isNaN(_phase)) {
			library_namespace.debug('資料還沒載入。', 2);
			return;
		}

		var phase = Math.floor(_phase);

		// 假如變換剛好落在隔日子夜0時剛開始(這機率應該極低)，則今日還是應該算前一個。
		// 因為月相長度大於日長度，此即表示今天還沒變換月相。
		if (phase !== _phase
		// 檢查今天子夜0時與明日子夜0時是否有改變月相。
		&& phase !== (_phase = Math.floor(lunar_phase_angle_of_JD(TT_JD) / 90))) {
			// UT_JD, UT_JD+1 有不同月相，表示這天中改變了月相。
			// phase: −2–1
			if (phase < 0)
				phase += 4;
			// phase: 0–3
			var phase_shown = options.index ? phase : LUNAR_PHASE_NAME[phase];
			if (options.time || options.eclipse) {
				// 發生此月相之實際 TT in JD.
				var TT = accurate_lunar_phase(
						Julian_century(TT_JD) * 100 + 2000, phase, {
							JD : TT_JD,
							// eclipse : true,
							nearest : true
						});
				phase_shown = [ phase_shown, UT_of(TT) ];
				/**
				 * @see
				 * 
				 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
				 * p. 380. chapter 54
				 * 
				 * If F differs from the nearest multiple of 180° by less than
				 * 13.9 degrees, then there is certainly an eclipse; ifthe
				 * difference is larger than 21°, there is no eclipse;
				 * 
				 * Use can be made of the following rule: there is no eclipse if
				 * |sin F| > 0.36.
				 */
				if (options.eclipse
				// 0:朔才可能日食, 2:望才可能月食
				&& (phase === 0 || phase === 2)) {
					/**
					 * 日月食資訊。
					 * 
					 * @type {Object}
					 */
					var eclipse_data
					//
					= eclipse_JD(TT, phase, options);

					if (eclipse_data) {
						// 遮到了。
						phase_shown.push(eclipse_data);
					}
				}
			}
			// [ phase type index, UT (JD), eclipse_data ]
			return phase_shown;
		}

		if (options.晦 && phase === -1 && 0 ===
		// +2: 晦日午夜之2天之後(之午夜)恰好過朔。phase: -1 → -1 → 0
		Math.floor(lunar_phase_angle_of_JD(TT_JD + 2) / 90))
			return options.晦 === true ? '晦' : options.晦;
	}

	_.lunar_phase_of_JD = lunar_phase_of_JD;

	// ------------------------------------------------------------------------------------------------------//
	// 制曆/排曆/排陰陽曆譜
	// 中國傳統曆法是一種陰陽合曆，以月相定月份，以太陽定年周期。
	// TODO: 孫郁興 中國各朝曆法及其基數變遷: 沈括提出以「十二氣」為一年的曆法，十二氣曆

	/**
	 * normalize minute offset.
	 * 
	 * @param {Number}minute_offset
	 *            time-zone offset from UTC in minutes.<br />
	 *            e.g., UTC+8: 8 * 60 = 480
	 * 
	 * @returns {Number} normalized minute offset
	 */
	function normalize_minute_offset(minute_offset) {
		return isNaN(minute_offset) ? default_offset : minute_offset;
	}

	/**
	 * JD (UT) to local midnight (00:00).
	 * 
	 * @param {Number}UT_JD
	 *            Julian date (JD of 日常生活時間 UT)
	 * @param {Number}[minute_offset]
	 *            time-zone offset from UTC in minutes.<br />
	 *            e.g., UTC+8: 8 * 60 = +480. default: UTC+0.
	 * @param {Boolean}[get_local_Date]
	 *            轉成當地之 Date
	 * 
	 * @returns {Number|Date}
	 */
	function midnight_of(UT_JD, minute_offset, get_local_Date) {
		// -day_offset: to local (UT_JD+.5). 此時把 local 當作 UTC+0.
		// Math.floor(): reset to local midnight, 00:00
		// +day_offset: recover to UTC
		var day_offset = (minute_offset | 0) / (ONE_DAY_HOURS * 60) - .5;
		UT_JD = Math.floor(UT_JD + day_offset) - day_offset;

		if (get_local_Date) {
			UT_JD = library_namespace.JD_to_Date(
			//
			UT_JD + (minute_offset - default_offset) / (60 * ONE_DAY_HOURS));
			// 歸零用。
			var ms = UT_JD.getMilliseconds();
			// 歸零。
			if (ms)
				UT_JD.setMilliseconds(Math.round(ms / 500) * 500);
		}

		return UT_JD;
	}

	_.midnight_of = midnight_of;

	/**
	 * 冬至序 = 18
	 * 
	 * @type {Integer}
	 */
	var 冬至序 = SOLAR_TERMS_NAME.indexOf('冬至');

	/**
	 * 取得整年之月首朔日/月齡。
	 * 
	 * 注意：若中氣發生於朔時刻之前、朔日當日子夜後，如清世祖順治2年閏6月1日，此中氣會被算做發生於當日，而非前一個月之晦日；因此閏月基本上會被排在上一個月而非本月。
	 * 
	 * @param {Integer}CE_year
	 *            公元年數
	 * @param {Number}minute_offset
	 *            time-zone offset from UTC in minutes.<br />
	 *            e.g., UTC+8: 8 * 60 = 480
	 * 
	 * @returns {Array} 年朔日 = [ [ Julian date (JD of 日常生活時間 UT), JD, ...], 冬至所在月 ]
	 */
	function 子月序(CE_year, minute_offset) {
		minute_offset = normalize_minute_offset(minute_offset);

		// 冬至所在月為十一月，之後為十二月、正月、二月……復至十一月。
		var 冬至 = solar_term_JD(CE_year, 冬至序),
		// 取得整年之朔日。依現行農曆曆法，每年以朔分月（朔日為每月初一）。
		年朔日 = lunar_phase(CE_year, 0, {
			duration : 1,
			mean : false
		})
		// 魯僖公五年正月壬子朔旦冬至
		.map(function(UT_JD) {
			// 日月合朔時間 → 朔日0時
			return midnight_of(UT_JD, minute_offset);
		});
		年朔日.冬至 = 冬至;

		var index = 年朔日.search_sorted(冬至, true);
		// assert: 冬至 >= 年朔日[index];

		return [ 年朔日, index ];
	}

	/**
	 * 取得歲首(建正/年始)為建子之整年月首朔日/月齡。
	 * 
	 * @param {Integer}年
	 *            基本上與公元年數同步。 e.g., 2000: 1999/12/8–2000/11/25
	 * @param {Number}minute_offset
	 *            time-zone offset from UTC in minutes.<br />
	 *            e.g., UTC+8: 8 * 60 = 480
	 * 
	 * @returns {Array} 年朔日 = [ {Number}朔日JD, 朔日JD, ... ]
	 */
	function 建子朔日(年, minute_offset) {
		minute_offset = normalize_minute_offset(minute_offset);

		var 朔日 = 子月序(年 - 1, minute_offset),
		//
		次年朔日 = 子月序(年, minute_offset);

		朔日[0].splice(0, 朔日[1]);
		朔日 = 朔日[0].concat(次年朔日[0].slice(0, 次年朔日[1]));
		朔日.end = 次年朔日[0][次年朔日[1]];

		if (朔日.length === 13) {
			// 確定/找閏月。
			// 若兩冬至間有13個月（否則應有12個月），則置閏於冬至後第一個沒中氣的月，月序與前一個月相同（閏月在幾月後面，就稱閏幾月）。
			var 中氣, 中氣序 = 冬至序 + 2, 閏 = 1, year = 年 - 1;
			for (; 中氣序 !== 冬至序; 中氣序 += 2) {
				if (中氣序 === SOLAR_TERMS_NAME.length)
					year++, 中氣序 -= SOLAR_TERMS_NAME.length;
				中氣 = solar_term_JD(year, 中氣序);
				朔日[SOLAR_TERMS_NAME[中氣序]] = 中氣;
				if (中氣 >= 朔日[閏]
				// 測中氣序: 朔日[閏]: 沒中氣的月
				&& 中氣 >= 朔日[++閏]) {
					閏--;
					// CeL.JD_to_Date(1727046.1666666667).format('CE')
					// CeL.JD_to_Date(1727076.9971438504).format('CE')
					library_namespace.debug('沒中氣的月: 朔日[' + 閏 + '] = ' + 朔日[閏]
							+ ', 中氣 ' + 中氣, 3);
					break;
				}
			}
			朔日.閏 = 閏;
		} else if (朔日.length !== 12)
			library_namespace.error(年 + '年有' + 朔日.length + '個月!');

		// [ {Number}朔日JD, 朔日JD, ... ].閏 = {Boolean};
		return 朔日;
	}

	/**
	 * 年朔日 = 朔日_cache[ 年 + '/' + minute_offset ]<br /> = [ {Number}朔日JD, 朔日JD,
	 * ... ]<br />
	 * e.g., [ 1727075.1666666667, 1727104.1666666667, ... ]
	 * 
	 * 年朔日.閏 = {Boolean};
	 * 
	 * @inner
	 */
	var 朔日_cache = [];

	/**
	 * clone 曆數
	 * 
	 * @param {String}index
	 *            cache index
	 * @param {Object}options
	 *            options
	 * @param {Array}[朔日]
	 *            本初年朔日曆數
	 * 
	 * @returns {Array} 年朔日曆數
	 * 
	 * @inner
	 */
	function clone_朔日(index, options, 朔日) {
		library_namespace.debug('Get cache index [' + index
				+ '] (年 /歲首/minute_offset)');
		if (朔日)
			朔日_cache[index] = 朔日;
		else if (!(朔日 = 朔日_cache[index]))
			return;

		if (options.月名 && !朔日.月名)
			朔日.月名 = 定朔.月名(朔日);

		var clone = 朔日.slice();
		clone.end = 朔日.end;
		if (options.月名)
			// 添加月名
			clone.月名 = 朔日.月名.slice();
		if (朔日.閏)
			clone.閏 = 朔日.閏;

		return clone;
	}

	/**
	 * 以定氣定朔法排曆，編排中國傳統曆法（陰陽曆），取得整年月首朔日/月齡。
	 * 
	 * @param {Integer}年
	 *            基本上與公元年數同步。 e.g., 2000: 1999/12/8–2000/11/25
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            {Number}options.minute_offset: time-zone offset from UTC in
	 *            minutes.<br />
	 *            e.g., UTC+8: 8 * 60 = 480<br />
	 *            {String|Integer}options.歲首: 年始之地支/地支序(0:子)<br />
	 *            {Integer}options.year_offset: 年數將自動加上此 offset。<br />
	 *            {Boolean}options.月名: 順便加上 .月名 = [ 月名 ]
	 * 
	 * @returns {Array} 年朔日 = [ {Number}朔日JD, 朔日JD, ... ]
	 */
	function 定朔(年, options) {
		if (!LEA406_loaded('V'))
			// 尚未載入指定天體/行星的計算數據。而採用低精度之誤差過大，不能用。
			return;

		// 前置處理。
		if (!library_namespace.is_Object(options))
			options = Object.create(null);

		var 歲首 = options.歲首,
		//
		minute_offset = options.minute_offset;

		if (library_namespace.is_Date(年)) {
			if (isNaN(minute_offset))
				minute_offset = 年[
				// see data.date.era
				library_namespace.era.MINUTE_OFFSET_KEY];
			年 = Math.round(年.getFullYear() + 年.getMonth() / 12);
		}

		minute_offset = normalize_minute_offset(minute_offset);

		if (!isNaN(options.year_offset))
			年 += options.year_offset;

		if (isNaN(歲首) && NOT_FOUND ===
		//
		(歲首 = library_namespace.BRANCH_LIST.indexOf(歲首))) {
			if (定朔.歲首 && isNaN(定朔.歲首)) {
				定朔.歲首 = library_namespace.BRANCH_LIST.indexOf(定朔.歲首);
				if (定朔.歲首 === NOT_FOUND) {
					library_namespace.warn('定朔: Invalid 歲首');
					定朔.歲首 = undefined;
				}
			}
			歲首 = 定朔.歲首;
		}

		// 至此已確定: 年, 歲首, minute_offset.

		var cache_index = 年 + '/' + 歲首 + '/' + minute_offset,
		//
		朔日 = clone_朔日(cache_index, options);
		if (朔日)
			return 朔日;

		朔日 = 建子朔日(年, minute_offset);

		if (歲首 === 0)
			return clone_朔日(cache_index, options, 朔日);

		var 閏 = 朔日.閏 - 歲首;
		library_namespace.debug('歲首 ' + 歲首 + ', ' + 朔日.閏 + ', 閏=' + 閏, 3);
		// 此處已清掉(朔日.閏)
		朔日 = 朔日.slice(閏 <= 0 ? 歲首 + 1 : 歲首);
		if (閏 > 0)
			朔日.閏 = 閏;

		var 次年朔日 = 建子朔日(年 + 1, minute_offset);
		library_namespace.debug('次年 ' + 歲首 + ', ' + 次年朔日.閏, 3);
		閏 = 次年朔日.閏;
		var index = 閏 <= 歲首 ? 歲首 + 1 : 歲首,
		//
		end = 次年朔日[index];
		library_namespace.debug(
		//
		'end[' + index + ']=' + 次年朔日[index], 3);
		次年朔日 = 次年朔日.slice(0, index);
		if (閏 <= 歲首)
			if (朔日.閏)
				// 這將造成無法阻絕一年內可能有兩閏月，以及一年僅有11個月的可能。
				library_namespace.error(年 + '年有兩個閏月!!');
			else
				朔日.閏 = 閏 + 朔日.length;

		閏 = 朔日.閏;
		library_namespace.debug('閏=' + 閏, 3);
		// 此處會清掉(朔日.閏)
		朔日 = 朔日.concat(次年朔日);
		朔日.end = end;
		if (閏)
			朔日.閏 = 閏;

		return clone_朔日(cache_index, options, 朔日);
	}

	// default 預設歲首為建寅
	// 正謂年始，朔謂月初，言王者得政，示從我始，改故用新，隨寅、丑、子所建也。周子，殷丑，夏寅，是改正也；周夜半，殷雞鳴夏平旦，是易朔也。
	定朔.歲首 = '寅';

	定朔.月名 = function(年朔日) {
		var 閏 = 年朔日.閏, 月序 = 0;
		library_namespace.debug('閏=' + 閏, 3);
		return 年朔日.map(function(朔, index) {
			return index === 閏 ? '閏' + 月序 : ++月序;
		});
	};

	_.定朔 = 定朔;

	/**
	 * 取得指定日期之夏曆。
	 * 
	 * @param {Date}date
	 *            指定日期。
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 * 
	 * @returns {Array} [ 年, 月, 日 ]
	 */
	function 夏曆(date, options) {
		if (!LEA406_loaded('V'))
			// 採用低精度之誤差過大，不能用。
			return;

		var JDN = library_namespace.Julian_day(date),
		//
		年朔日 = {
			月名 : true
		};
		options = options ? Object.assign(年朔日, options) : 年朔日;
		options.year_offset |= 0;
		年朔日 = 定朔(date, options);

		if (JDN < 年朔日[0]) {
			// date 實際上在上一年。
			options.year_offset--;
			年朔日 = 定朔(date, options);
		} else if (JDN >= 年朔日.end) {
			// date 實際上在下一年。
			options.year_offset++;
			年朔日 = 定朔(date, options);
		}

		var index = 年朔日.search_sorted(JDN, true);

		// [ 年, 月, 日 ]
		return [ date.getFullYear() + options.year_offset, 年朔日.月名[index],
				1 + JDN - 年朔日[index] | 0 ];
	}

	_.夏曆 = 夏曆;

	// ------------------------------------------------------------------------------------------------------//
	// 天體的升、中天、降

	/**
	 * 計算天體的升（出:星面頂之緯度負→正）、上中天（該天體正經過當地子午圈，但與緯度最高點的位置當有些微差別）、降（沒:星面底之緯度正→負）時刻。
	 * 天体の出没 e.g., 日出正午日落,太陽升降。 約有兩三分的精準度?
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * Chapter 15 Rising, Transit, and Setting
	 * 
	 * @param {Array}local
	 *            the observer's geographic location [ latitude (°), longitude
	 *            (°), time zone (e.g., UTC+8: 8), elevation or geometric height
	 *            (m) ]<br />
	 *            觀測者 [ 緯度（北半球為正,南半球為負）, 經度（從Greenwich向東為正，西為負）, 時區,
	 *            海拔標高(觀測者距海平面的高度) ]
	 * @param {Number}JDN
	 *            UT JDN
	 * @param {Number}type
	 *            0:lower culmination, 1:rise, 2:upper culmination, 3:set
	 * @param {String}object
	 *            天體 (e.g., planets 行星).
	 * @param {Boolean}force
	 *            即使預期應出現升降的時段，天體卻一直處於地平之同一側（同在地平線上或下），依然嘗試估算；取得即使不是當天，但符合的時點。
	 * 
	 * @returns {Number}UT JD
	 * 
	 * @see https://en.wikipedia.org/wiki/Sunrise_equation
	 *      https://en.wikipedia.org/wiki/Culmination
	 *      http://www.zhihu.com/question/23423763
	 *      http://www.astronomy.com.cn/bbs/thread-157520-1-1.html<br />
	 *      于Paul Schlyter的1992年的sunriset函数
	 *      http://www.spectralcalc.com/solar_calculator/solar_position.php
	 */
	function rise_set(local, JDN, type, object, force) {
		if (!object)
			object = SUN_NAME;
		if (type) {
			if (typeof type !== 'number' && !isNaN(type))
				type = +type;
		} else if (!type && type !== 0)
			// get [ 0下中天, 1升, 2上中天, 3降 ]
			type = [ 0, 1, 2, 3 ];
		if (Array.isArray(type)) {
			return type.map(function(type) {
				return rise_set(local, JDN, type, object, force);
			});
		}

		function angle(TT_JD) {
			coordinates = get_coordinates(TT_JD, {
				local : local,
				object : object
			});
			var angle = type % 2 === 1 || type > 3 ? coordinates.Alt + Δ
			// 上中天: LHA: 2π → 應為0
			// 下中天: LHA: 應為π
			: normalize_radians(coordinates.LHA + Δ, true);

			// 常需演算十數次。
			if (false)
				console.log(TT_JD + ' ('
				//
				+ library_namespace.JD_to_Date(TT_JD).format('CE') + ' TT): '
						+ angle);
			return angle;
		}

		var Δ, get_coordinates, coordinates,
		// 自動判別時區。
		zone = get_time_zone(local);

		// UT_JD: local 當地之 0:0
		var UT_JD = JDN - .5 - zone / ONE_DAY_HOURS,
		// hour 上下限
		hour0, hour1;

		// TODO: 考慮 dip of the horizon (地平俯角, 海岸視高差)
		// @see
		// https://en.wikipedia.org/wiki/Horizon#Effect_of_atmospheric_refraction
		// http://www-rohan.sdsu.edu/~aty/explain/atmos_refr/altitudes.html

		if (object === SUN_NAME) {
			Δ = SOLAR_RADIUS_RADIANS;
			get_coordinates = solar_coordinates;

		} else {
			get_coordinates = object === MOON_NAME ? lunar_coordinates
					: object_coordinates;
			coordinates = get_coordinates(TT_of(UT_JD), {
				local : local,
				object : object
			});

			// UT_JD 與上一個上中天之距離 (in days, 0~1)。
			Δ = normalize_radians(coordinates.LHA) / TURN_TO_RADIANS;

			// 決定要使用的下中天。

			// 確認最靠近 UT_JD 的下中天。
			if (Δ < .5) {
				// 正常情況:下中天 在本日上半天。
			} else {
				// 下中天 在前一日下半天。

				// TODO: 本日 0:0 後首個下中天。
				// UT_JD += 1;

				// 取前一個下中天。
			}

			UT_JD += .5 - Δ;

			Δ = object === MOON_NAME
			// http://aa.usno.navy.mil/faq/docs/RST_defs.php
			// Moon's apparent radius varies from 15 to 17 arcminutes
			// and its horizontal parallax varies from 54 to 61
			// arcminutes.
			? Math.atan(LUNAR_RADIUS_M / AU_TO_METERS / coordinates.Δ)
			// 其他天體之 apparent radius 當作0。
			: 0;
		}

		// Δ: 天體之 apparent radius (in radians)

		switch (type) {
		case 0:
			// 下中天
			hour0 = -2;
			hour1 = 2;
			Δ = -TURN_TO_RADIANS / 2;
			break;
		case 2:
			// 上中天, 過中天
			hour0 = ONE_DAY_HOURS / 2 - 2;
			hour1 = ONE_DAY_HOURS / 2 + 2;
			Δ = 0;
			break;

		case 1:
			// 升
			// http://tamweb.tam.gov.tw/v3/tw/content.asp?mtype=c2&idx=1255
			// 夏至並非一年中日出最早、日落最晚之時
			hour0 = 0;
			hour1 = ONE_DAY_HOURS / 2;
			break;
		case 3:
			// 降
			hour0 = ONE_DAY_HOURS / 2;
			hour1 = ONE_DAY_HOURS;
			break;

		// civil twilight, nautical twilight, astronomical twilight
		case 4:
		case 5:
		case 6:
			hour0 = 0;
			hour1 = ONE_DAY_HOURS / 2;
			Δ = (7 - type) * 6 * DEGREES_TO_RADIANS;
			break;

		case 7:
		case 8:
		case 9:
			hour0 = ONE_DAY_HOURS / 2;
			hour1 = ONE_DAY_HOURS;
			Δ = (type - 6) * 6 * DEGREES_TO_RADIANS;
			break;

		default:
			throw new Error('rise_set: Invalid type: [' + type + ']');
		}

		/**
		 * 天文/航海/民用曙暮光(晨起天亮/晚上天黑)時刻。
		 * http://aa.usno.navy.mil/faq/docs/RST_defs.php
		 * <q>Civil twilight is defined to begin in the morning, and to end in the evening when the center of the Sun is geometrically 6 degrees below the horizon.</q>
		 * <br />
		 * <q>Nautical twilight is defined to begin in the morning, and to end in the evening, when the center of the sun is geometrically 12 degrees below the horizon.</q>
		 * <br />
		 * <q>Astronomical twilight is defined to begin in the morning, and to end in the evening when the center of the Sun is geometrically 18 degrees below the horizon.</q>
		 * <br />
		 */

		// 檢測分布
		if (false)
			for (var m = 0; m < 4 * 60; m++)
				angle(TT_of(UT_JD + hour0 / ONE_DAY_HOURS + m / ONE_DAY_HOURS
						/ 60));

		UT_JD = UT_of(library_namespace.find_root(angle, TT_of(UT_JD + hour0
				/ ONE_DAY_HOURS), TT_of(UT_JD + hour1 / ONE_DAY_HOURS), 0,
		// 即使預期應出現升降的時段，天體卻一直處於地平之同一側(同在地平線上或下)，依然嘗試估算。
		force ? null : {
			start_OK : function(y0, y1) {
				// console.log([ y0, y1 ]);
				return Math.sign(y0) !== Math.sign(y1);
			}
		}));

		// 出沒方位角。
		coordinates.Az;
		// 過中天仰角。
		coordinates.Alt;

		return UT_JD;
	}

	_.rise_set = rise_set;

	/**
	 * name of type rise_set() gets.<br />
	 * <q>下中天,升,上中天,降</q>
	 * 
	 * @type {Array}
	 */
	rise_set.type_name = [
	// gettext_config:{"id":"lower-culmination"}
	"lower culmination",
	// gettext_config:{"id":"sunrise","mark_type":"combination_message_id"}
	// gettext_config:{"id":"moonrise","mark_type":"combination_message_id"}
	"rise",
	// gettext_config:{"id":"upper-culmination"}
	"upper culmination",
	// gettext_config:{"id":"sunset","mark_type":"combination_message_id"}
	// gettext_config:{"id":"moonset","mark_type":"combination_message_id"}
	"set" ];

	'astronomical,nautical,civil'.split(',')
	//
	.forEach(function(twilight, index) {
		// gettext_config:{"id":"astronomical-twilight-begin","mark_type":"combination_message_id"}
		// gettext_config:{"id":"nautical-twilight-begin","mark_type":"combination_message_id"}
		// gettext_config:{"id":"civil-twilight-begin","mark_type":"combination_message_id"}
		rise_set.type_name[4 + index] = twilight + ' twilight begin';
		// gettext_config:{"id":"astronomical-twilight-end","mark_type":"combination_message_id"}
		// gettext_config:{"id":"nautical-twilight-end","mark_type":"combination_message_id"}
		// gettext_config:{"id":"civil-twilight-end","mark_type":"combination_message_id"}
		rise_set.type_name[9 - index] = twilight + ' twilight end';
	});

	// ------------------------------------------------------------------------------------------------------//
	// coordinates 統合 API

	/**
	 * 太陽名稱。
	 * 
	 * @type {String}
	 */
	var SUN_NAME = 'sun'.toLowerCase(),
	/**
	 * 月亮名稱。
	 * 
	 * @type {String}
	 */
	MOON_NAME = 'moon'.toLowerCase();

	/**
	 * 天體位置統合 API。
	 * 
	 * @param {String}object
	 *            天體名稱 (planets 行星).
	 * @param {Nunber|String|Date}date
	 *            UT (or TT).
	 * @param {Array}local
	 *            the observer's geographic location [ latitude (°), longitude
	 *            (°), time zone (e.g., UTC+8: 8), elevation or geometric height
	 *            (m) ]<br />
	 *            觀測者 [ 緯度（北半球為正,南半球為負）, 經度（從Greenwich向東為正，西為負）, 時區,
	 *            海拔標高(觀測者距海平面的高度) ]
	 * @param {Object}[options]
	 *            附加參數/設定特殊功能與選項:<br />
	 *            {Boolean}options.TT: date is TT instead of UT.
	 * 
	 * @constructor
	 */
	function Coordinates(object, date, local, options) {
		// object name
		this.object = object = Coordinates.normalize_object(object);
		// 先行載入必須的 terms。
		// 對 sun, moon 特別處理。
		if (object === MOON_NAME) {
			if (!LEA406_loaded('V'))
				LEA406_load_terms('V');
			if (!LEA406_loaded('U'))
				LEA406_load_terms('U');
			if (local && !LEA406_loaded('R'))
				LEA406_load_terms('R');
		} else if (object !== SUN_NAME) {
			object = VSOP87.object_name(object);
			if (!(object in VSOP87_terms))
				VSOP87_load_terms(object);
		}
		object = VSOP87.object_name(solar_terms_object);
		if (!(object in VSOP87_terms))
			VSOP87_load_terms(object);

		// use google map longitude latitude picker
		if (local)
			this.local = local;

		// 紀錄時間。
		this.JD = Number.isFinite(date) ? date : library_namespace.Julian_day
				.JD(date);
		if (options && options.TT)
			this.UT = UT_of(this.TT = this.JD);
		else
			this.TT = TT_of(this.UT = this.JD);
	}

	_.celestial_coordinates = Coordinates;

	Coordinates.object_alias = {
		solar : SUN_NAME,
		lunar : MOON_NAME
	};
	// normalize object name
	Coordinates.normalize_object = function(name) {
		name = name.toLowerCase();
		if (name in Coordinates.object_alias)
			name = Coordinates.object_alias[name];
		return name;
	};

	/**
	 * 設定 coordinates。
	 * 
	 * @param {String}type
	 *            one of DSGETH
	 * @param {Object}coordinates
	 *            coordinates get through get_horizontal()
	 * 
	 * @returns {Object}coordinates
	 * 
	 * @inner
	 */
	function set_coordinates(type, coordinates) {
		// reset property to cache.
		Object.defineProperty(this, type, {
			value : coordinates
		});
		return coordinates;
	}

	/**
	 * 一次把 E地心赤道, T站心赤道, H站心地平 全部設定完。
	 * 
	 * @param {Object}coordinates
	 *            coordinates get through get_horizontal()
	 * 
	 * @inner
	 */
	function set_horizontal_coordinates(coordinates) {
		this.s('E', [ normalize_radians(coordinates.α),
		//
		normalize_radians(coordinates.δ, true), coordinates.Δ ]);
		this.s('H', coordinates.Az ? [ normalize_radians(coordinates.Az),
				normalize_radians(coordinates.Alt, true) ]
		// 站心地平座標 .Az, .Alt 比較可能未設定。
		: undefined);
		// the equatorial horizontal parallax of the body in radians.
		// 天體的赤道地平視差.
		// CeL.format_radians(coordinates.π)
		if (coordinates.π)
			this.π = coordinates.π;
		// LHA: local hour angle (in radians) 本地地心時角。
		if (coordinates.LHA)
			this.LHA = coordinates.LHA;
		// elongation Ψ of the planet, its angular distance to the Sun
		// https://en.wikipedia.org/wiki/Elongation_%28astronomy%29
		// 行星的距角，即地心看行星與太陽的角距離。
		if (coordinates.Ψ)
			this.elongation = coordinates.Ψ;
		// semi-diameter (in arcseconds). 天體的中心視半徑。
		this.semidiameter = semidiameter(coordinates, this.object);
		this.s('T', (coordinates = coordinates.T) ? [
				normalize_radians(coordinates[0]),
				normalize_radians(coordinates[1], true) ]
		// coordinates.T 可能未設定。
		: undefined);
	}

	/**
	 * @inner
	 */
	function get_dimension(coordinates, type) {
		if (type.includes('longitude'))
			return coordinates[0];
		if (type.includes('latitude'))
			return coordinates[1];
		return coordinates;
	}

	/**
	 * 取得指定類型之座標。
	 * 
	 * @param {String}type
	 *            指定類型/symbols
	 * 
	 * @returns {Object|Number}座標
	 * 
	 * @see https://en.wikipedia.org/wiki/Celestial_coordinate_system#Coordinate_systems
	 */
	function get_coordinates(type) {
		if (typeof type === 'string' && type.includes(','))
			type = type.split(/,+/);
		if (Array.isArray(type))
			return type.map(get_coordinates.bind(this));

		type = String(type).toLowerCase().split(/[\s\-]+/).join(' ');
		if (type.includes('λ'))
			return this.G[0];
		if (type.includes('β'))
			return this.G[1];
		if (type.includes('distance'))
			return this.G[2];
		if (type.includes('α'))
			return this.E[0];
		// 注意: 'Δ'.toLowerCase() === 'δ'
		if (type.includes('δ'))
			return this.E[1];
		// Azimuth, Altitude
		if (type.includes('az'))
			return this.H && this.H[0];
		if (type.includes('alt'))
			return this.H && this.H[1];

		if (type.includes('dynamic'))
			return get_dimension(this.D, type);
		// after detect dynamical
		if (type.includes('heliocentric'))
			return get_dimension(this.S, type);

		if (type.includes('horizontal'))
			return get_dimension(this.H, type);
		// after detect horizontal
		if (type.includes('topocentric'))
			return get_dimension(this.T, type);

		// after detect heliocentric, topocentric
		if (type.includes('equatorial'))
			return get_dimension(this.E, type);
		// after detect equatorial
		if (type.includes('geocentric') || type.includes('ecliptic'))
			return get_dimension(this.G, type);

		// TODO: rectangular

		if ((type[0] in this)
		//
		&& typeof this[type[0]] !== 'function')
			return this[type[0]];

		// 只輸入經緯度時，預設當作 G地心視黃道: 地心視黃經/地心視黃緯
		type = get_dimension(this.G, type);
		if (typeof type === 'number')
			return type;
	}

	Object.defineProperties(Coordinates.prototype, {
		s : {
			enumerable : false,
			value : set_coordinates
		},
		sh : {
			enumerable : false,
			value : set_horizontal_coordinates
		},
		c : {
			value : get_coordinates
		}
	});

	// ----------------------------------------------------------------------------

	// 計算順序:
	// @see
	// https://github.com/kanasimi/IAU-SOFA/blob/master/doc/sofa_ast_c.pdf

	// :: VSOP87 進入點→
	// 日心黃道: D日心瞬時黃道 by VSOP87
	// (太陽: 日心黃道: FK5) (FK5 2選1)
	// (天體/行星: S日心視黃道:修正光行時及光行差) (修正光行時及光行差 2選1)
	// 地心直角黃道座標 = 天體S日心視黃道 - 地球S日心視黃道
	// G地心視黃道: 球座標
	// :: LEA406 進入點: 計算月亮位置(地心瞬時黃道坐標)
	// (天體/行星: G地心視黃道: FK5? why here?) (FK5 2選1)
	// (G地心視黃道: 修正月亮光行時及太陽光行差) (修正光行時及光行差 2選1)
	// G地心視黃道: 修正地球章動 nutation。
	//
	// E地心赤道座標:
	// topocentric(本地站心)(T站心赤道): 修正恆星時/經緯度/時角, 行星視差
	// H站心地平座標: 修正大氣折射

	// D日心瞬時黃道 heliocentric dynamical ecliptic coordinate system
	// [ longitude 黃經(radians), latitude 黃緯(radians), distance 距離(AU) ]
	Coordinates.D = function() {
		var coordinates;
		if (this.object === MOON_NAME) {
			// LEA406 計算月亮位置(地心瞬時黃道坐標)
			coordinates = LEA406(this.TT, {
				FK5 : false
			});
			coordinates = [
					normalize_radians(coordinates.V + TURN_TO_RADIANS / 2),
					normalize_radians(-coordinates.B, true), coordinates.R ];
		} else if (this.object === SUN_NAME)
			// 日心瞬時黃道以太陽為中心。
			coordinates = [ 0, 0, 0 ];
		else {
			var tmp_c = object_coordinates(this.TT, this.object, {
				equatorial : true,
				local : this.local,
				elongation : true
			});
			// S日心視黃道 heliocentric ecliptic coordinate system
			coordinates = tmp_c.S;
			this.s('S', [ normalize_radians(coordinates.L),
					normalize_radians(coordinates.B, true), coordinates.R ]);
			coordinates = tmp_c;
			this.s('G', [ normalize_radians(coordinates.λ),
					normalize_radians(coordinates.β, true), coordinates.Δ ]);

			this.sh(coordinates);

			// D日心瞬時黃道 heliocentric dynamical ecliptic coordinate system
			coordinates = tmp_c.D;
			coordinates
			// 
			= [ normalize_radians(coordinates.L),
					normalize_radians(coordinates.B, true), coordinates.R ];
		}

		return this.s('D', coordinates);
	};

	// S日心視黃道 heliocentric ecliptic coordinate system
	// [ longitude 黃經(radians), latitude 黃緯(radians), distance 距離(AU) ]
	Coordinates.S = function() {
		var coordinates;
		if (this.object === MOON_NAME) {
			coordinates = this.G;
			coordinates = dynamical_to_FK5({
				L : coordinates[0],
				B : coordinates[1]
			}, Julian_century(this.TT) / 10);
			coordinates = [ coordinates.L, coordinates.B, this.G[2] ];
		} else if (this.object === SUN_NAME)
			// 日心黃道以太陽為中心。
			coordinates = [ 0, 0, 0 ];
		else {
			return this.D && this.S;
		}

		return this.s('S', coordinates);
	};

	// G地心視黃道 geocentric solar ecliptic coordinate system
	// [ longitude λ黃經(radians), latitude β黃緯(radians), distance 距離(AU)
	// ]
	Coordinates.G = function() {
		var coordinates;
		if (this.object === MOON_NAME) {
			coordinates = lunar_coordinates(this.TT, {
				equatorial : true,
				local : this.local,
				elongation : true
			});

			this.sh(coordinates);

			coordinates
			//
			= [ coordinates.λ, coordinates.β, coordinates.Δ ];
		} else if (this.object === SUN_NAME) {
			coordinates = solar_coordinates(this.TT, {
				equatorial : true,
				local : this.local,
				elongation : true
			});

			this.sh(coordinates);

			// coordinates.apparent or use coordinates.L
			coordinates = [ coordinates.apparent * DEGREES_TO_RADIANS,
					coordinates.β, coordinates.Δ ];
		} else {
			return this.D && this.G;
		}

		return this.s('G', coordinates);
	};

	// E地心赤道 geocentric equatorial coordinate system
	// [ right ascension α赤經(radians), declination δ赤緯(radians),
	// distance 距離(AU) ]
	Coordinates.E = function() {
		// eval
		return this.G && this.E;
	};

	// T站心赤道 topocentric equatorial coordinate system
	// [ right ascension α赤經(radians), declination δ赤緯(radians) ]
	Coordinates.T = function() {
		// eval
		return this.G && this.T;
	};

	// H站心地平 topocentric horizontal coordinate system
	// [ Azimuth (Az) 方位角又稱地平經度, Altitude (Alt) 高度角或仰角又稱地平緯度 ]
	Coordinates.H = function() {
		// eval
		return this.G && this.H;
	};

	// D日心瞬時黃道 heliocentric dynamical ecliptic coordinate system
	// S日心視黃道 heliocentric ecliptic coordinate system
	// G地心視黃道 geocentric solar ecliptic coordinate system
	// E地心赤道 geocentric equatorial coordinate system
	// T站心赤道 topocentric equatorial coordinate system
	// H站心地平 topocentric horizontal coordinate system
	'DSGETH'.split('').forEach(function(type) {
		if (Object.defineProperty[library_namespace.env.not_native_keyword])
			// e.g., IE8
			return;

		// type: to [ radians, radians, AU ]
		Object.defineProperty(Coordinates.prototype, type, {
			enumerable : true,
			get : Coordinates[type]
		});
		// type + 'd': to [ degrees, degrees, meters ]
		Object.defineProperty(Coordinates.prototype, type + 'd', {
			enumerable : true,
			get : function() {
				var c = [ this[type][0] / DEGREES_TO_RADIANS,
				//
				this[type][1] / DEGREES_TO_RADIANS ];
				if (this[type].length > 2)
					c.push(this[type][2] * AU_TO_METERS);
				this.s(type + 'd', c);
				return c;
			}
		});
	});

	// 天球坐標系統
	// Celestial coordinate system
	// https://en.wikipedia.org/wiki/Celestial_coordinate_system
	// International Celestial Reference System
	// 國際天體參考系統（ICRS）原點在太陽系重心

	// 中心/質量中心 center point (origin)
	// https://en.wikipedia.org/wiki/Centre_%28geometry%29
	// H 日心 heliocentric
	// G 地心 geocentric, Earth-centered
	// T 本地站心,觀測中心座標系,視心 topocentric, local, observer's

	// 基礎平面/基面 fundamental plane of reference
	// https://en.wikipedia.org/wiki/Fundamental_plane_%28spherical_coordinates%29
	// https://en.wikipedia.org/wiki/Plane_of_reference
	// https://en.wikipedia.org/wiki/Celestial_coordinate_system#Coordinate_systems
	// D 瞬時黃道 dynamical ecliptic
	// S 黃道 ecliptic, solar
	// E 赤道 equatorial, celestial equator
	// H 地平 horizontal, observer's horizon
	//
	// G 銀道坐標系，又作銀道座標系 galactic
	// SG 超星系坐標系統 Supergalactic

	// position, seen position
	// https://en.wikipedia.org/wiki/Apparent_place
	// A 視 apparent
	// T 真 true

	// coordinates
	// S 球 spherical
	// e.g., 日心黃道直角座標系
	// R 直角正交 rectangular, cartesian (three-dimensional), orthogonality

	// 維度 dimension
	// https://en.wikipedia.org/wiki/Dimension
	// https://en.wikipedia.org/wiki/Geographic_coordinate_system
	// L 經度 longitude
	// B 緯度 latitude
	// R 距離 radius or elevation
	//
	// X →x
	// Y ↑y
	// Z ↗z

	// ----------------------------------------------------------------------------------------------------------------------------------------------//

	/**
	 * 計算月亮近地點 perigee 和遠地點 apogee 的修正量。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 355. Chapter 50 Perigee and apogee of the Moon<br />
	 * 
	 * @param {Array}coefficients
	 *            修正量係數。
	 * @param {Array}c2
	 *            修正量係數2: [ D, M, F, T ]
	 * @param {Number}starts
	 *            初始值
	 * @param {Boolean}parallax
	 *            is parallax
	 * 
	 * @returns {Number}月亮近地點 perigee 和遠地點 apogee 的值。
	 * 
	 * @inner
	 */
	function lunar_perigee_apogee_Δ
	//
	(coefficients, c2, starts, parallax) {
		return coefficients.reduce(function(Δ, c) {
			// 三角函數係數, T之係數.
			var tc = 0, Tc = c[3];
			if (c[0])
				// D
				tc += c[0] * c2[0];
			if (c[1])
				// M
				tc += c[1] * c2[1];
			if (c[2])
				// F
				tc += c[2] * c2[2];
			if (c[4])
				Tc += c[4] * c2[3];
			return Δ + Tc * (parallax ? Math.cos(tc) : Math.sin(tc));
		}, starts);
	}

	/**
	 * 月亮的近地點 perigee 和遠地點 apogee。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 355. Chapter 50 Perigee and apogee of the Moon<br />
	 * 
	 * @param {Number}year_month
	 *            帶小數點的年數，例如1987.25表示1987年3月末。
	 * @param {Boolean}apogee
	 *            get apogee 遠地點
	 * 
	 * @returns {Array}[ TT in JD, 距離 in km, Moon's Equatorial Horizontal
	 *          Parallax in radians ]
	 * 
	 * @see https://github.com/helixcn/skycalc/blob/master/src/AAMoonPerigeeApogee.cpp
	 */
	function lunar_perigee_apogee(year_month, apogee) {
		// Mean time of perigee or apogee.
		// k是整數對應近點，增加0.5則是遠點。其它k值無意義。
		// 當k=0時，對應1999年12月22日的近點。
		/**
		 * 1999.971:
		 * <q>1999 + (2451534.6698 - CeL.Julian_day.from_YMD(1999, 1, 1, 'CE')) / (DAYS_OF_JULIAN_CENTURY / 100) = 1999.9710329911014363</q>
		 * 26.511:
		 * <q>DAYS_OF_JULIAN_CENTURY / 100 / 27.55454989 * 2 = 13.25552409522593 * 2 = 26.51104819045186</q>
		 */
		var k = (year_month - 1999.971) * 26.511;
		k = apogee ? Math.round((k - 1) / 2) + .5 : Math.round(k / 2);
		// T is the time in Julian centuries since the epoch 2000.0.
		var T = k / 1325.55,
		// 修正量係數2
		c2 = [ polynomial_value(lunar_perigee_apogee_D, T),
				polynomial_value(lunar_perigee_apogee_M, T),
				polynomial_value(lunar_perigee_apogee_F, T), T ],
		// the time of the mean perigee or apogee
		// 計算近點或遠點時刻
		// 與ELP-2000/82理論的精準結果比較，最大誤差如下：
		// 時間的誤差：近地點31分，遠地點3分
		// 視差的誤差：近地點0″.124，遠地點0″.051
		// 相應的距離誤差分別是：12km和6km
		TT_JD = lunar_perigee_apogee_Δ(apogee ? apogee_coefficients_JD
				: perigee_coefficients_JD, c2, polynomial_value(
				lunar_perigee_apogee_T, T)),
		// The corresponding value of the Moon's equatorial horizontal
		// Moon's Equatorial Horizontal Parallax 月亮赤道地平視差修正量 in radians
		parallax = lunar_perigee_apogee_Δ(apogee ? apogee_coefficients_parallax
				: perigee_coefficients_parallax, c2, 0, true)
				* ARCSECONDS_TO_RADIANS;

		if (false)
			console.log('→ starts ' + TT_JD + ' ('
					+ library_namespace.JD_to_Date(TT_JD).format('CE') + '): '
					+ LEA406(TT_JD, {
						km : true
					}).R);

		// CeL.LEA406.load_terms('R');
		// find_minima() 會因輸入而有秒單位的誤差偏移。
		TT_JD = library_namespace.find_minima(function(TT_JD) {
			var distance = LEA406(TT_JD, {
				km : true
			}).R;
			if (false)
				console.log(TT_JD + ' ('
				//
				+ library_namespace.JD_to_Date(TT_JD).format('CE') + '): '
						+ distance);
			// find_minima: 求取局部極小值
			return apogee ? -distance : distance;
		},
		// (31+1)/60/24≈1/45
		TT_JD - 1 / 45, TT_JD + 1 / 45);

		if (apogee)
			TT_JD[1] = -TT_JD[1];
		TT_JD.push(parallax);
		// [ TT in JD, 距離 in km, 月亮赤道地平視差修正量 in radians ]
		return TT_JD;
	}

	_.lunar_perigee_apogee = lunar_perigee_apogee;

	// ----------------------------------------------------------------------------------------------------------------------------------------------//

	/**
	 * data section: 以下為計算用天文數據。
	 */

	// ------------------------------------------------------------------------------------------------------//
	// terms for ΔT
	/**
	 * terms for function ΔT()
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * <a href="http://eclipse.gsfc.nasa.gov/SEcat5/deltatpoly.html"
	 * accessdate="2015/3/26 20:8">NASA - Polynomial Expressions for Delta T</a><br />
	 * <a href="http://www.staff.science.uu.nl/~gent0113/deltat/deltat_old.htm"
	 * accessdate="2015/3/26 20:7">Delta T: Pre-Telescopic Era</a>
	 * 
	 * @inner
	 */
	var ΔT_year_start = [ 2150, 2050, 2005, 1986, 1961, 1941, 1920, 1900, 1860,
			1800, 1700, 1600, 500, -500 ],
	// http://eclipse.gsfc.nasa.gov/SEcat5/deltatpoly.html
	// All values of ΔT based on Morrison and Stephenson [2004]
	// assume a value for the Moon's secular acceleration of -26
	// arcsec/cy².
	ΔT_year_base = [ 1820, 1820, 2000, 2000, 1975, 1950, 1920, 1900, 1860,
			1800, 1700, 1600, 1000, 0 ],
	// 為統合、方便計算，在演算方法上作了小幅變動。
	ΔT_coefficients = [
			[ -20, 0, 32 ],
			[ -205.724, 56.28, 32 ],
			[ 62.92, 32.217, 55.89 ],
			[ 63.86, 33.45, -603.74, 1727.5, 65181.4, 237359.9 ],
			[ 45.45, 106.7, -10000 / 260, -1000000 / 718 ],
			[ 29.07, 40.7, -10000 / 233, 1000000 / 2547 ],
			[ 21.20, 84.493, -761.00, 2093.6 ],
			[ -2.79, 149.4119, -598.939, 6196.6, -19700 ],
			[ 7.62, 57.37, -2517.54, 16806.68, -44736.24, 10000000000 / 233174 ],
			[ 13.72, -33.2447, 68.612, 4111.6, -37436, 121272, -169900, 87500 ],
			[ 8.83, 16.03, -59.285, 133.36, -100000000 / 1174000 ],
			[ 120, -98.08, -153.2, 1000000 / 7129 ],
			[ 1574.2, -556.01, 71.23472, 0.319781, -0.8503463, -0.005050998,
					0.0083572073 ],
			[ 10583.6, -1014.41, 33.78311, -5.952053, -0.1798452, 0.022174192,
					0.0090316521 ] ];

	// ------------------------------------------------------------------------------------------------------//
	// terms for obliquity 轉軸傾角

	/**
	 * IAU2006 obliquity coefficients.<br />
	 * terms for function mean_obliquity_IAU2006()
	 * 
	 * Reference 資料來源/資料依據:
	 * https://github.com/kanasimi/IAU-SOFA/blob/master/src/obl06.c
	 * 
	 * @inner
	 */
	var IAU2006_obliquity_coefficients = [
	// Astronomical Almanac 2011:
	// Mean obliquity of the ecliptic, epsilon_0:
	// epsilon_J2000.0 = 84381.406″ ± 0.001″
	84381.406, -46.836769, -0.0001831, 0.00200340, -0.000000576, -0.0000000434 ];

	/**
	 * terms for function equinox()
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * chapter 章動及黃赤交角.
	 * 
	 * @inner
	 */
	var Laskar_obliquity_coefficients = [
	// ε = 23° 26′ 21.448″ - 4680.93″ T - 1.55″ T²
	// + 1999.25″ T³ - 51.38″ T⁴ - 249.67″ T⁵
	// - 39.05″ T⁶ + 7.12″ T⁷ + 27.87″ T⁸ + 5.79″ T⁹ + 2.45″ T¹⁰
	23 * 60 * 60 + 26 * 60 + 21.448, -4680.93, -1.55, 1999.25, -51.38, -249.67,
			-39.05, 7.12, 27.87, 5.79, 2.45 ];
	Laskar_obliquity_coefficients.forEach(function(v, index) {
		Laskar_obliquity_coefficients[index] = v / DEGREES_TO_ARCSECONDS;
	});

	// ------------------------------------------------------------------------------------------------------//
	// terms for precession

	var
	/**
	 * terms for function ecliptic_precession()
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Kai Tang (2015). A long time span relativistic precession model of the
	 * Earth.<br />
	 * Table B.1 The Periodic Terms in PA, QA.
	 * 
	 * @inner
	 */
	唐凯_ecliptic_precession_terms = [ [ -3720, 1260, -1290, -3698, 68975 ],
			[ 657, -2585, 2508, 736, 235535 ],
			[ -2068, -302, 288, -2056, 72488 ],
			[ -855, -570, 548, -838, 192342 ], [ 438, 338, -334, 435, 49178 ],
			[ 309, 255, -225, 289, 67341 ], [ 217, 322, -191, 5, 424863 ],
			[ 168, -313, 288, 183, 65723 ], [ -278, 130, -112, -294, 173673 ],
			[ -278, -79, 89, -285, 75817 ], [ -77, 258, -157, -194, 255871 ],
			[ -24, 124, -106, -33, 64138 ], [ 29, 3, -91, 187, 496536 ],
			[ -135, -153, 176, -151, 70820 ], [ -85, 124, -257, 187, 1080090 ],
			[ 153, -276, 395, -117, 1309223 ], [ 14, -12, 77, -94, 663722 ],
			[ 55, -11, 46, 20, 214239 ], [ 81, 39, -41, 92, 77777 ],
			[ -55, -16, 19, -61, 80440 ], [ 6, -88, -50, 206, 367386 ],
			[ -22, 107, 16, -189, 321366 ], [ 5, -130, 24, 141, 284995 ],
			[ 11, -28, 8, 27, 164405 ], [ 15, 19, -19, 19, 83199 ] ],

	/**
	 * terms for function precession()
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Kai Tang (2015). A long time span relativistic precession model of the
	 * Earth.<br />
	 * Table B.2 The Periodic Terms in pA, εA.
	 * 
	 * @inner
	 */
	唐凯_precession_terms = [ [ -6653, -2199, 739, -2217, 40938 ],
			[ -3349, 541, -175, -1126, 39803 ],
			[ 1526, -1218, 376, 469, 53789 ], [ 227, 874, -313, 84, 28832 ],
			[ -370, 256, -91, -129, 29639 ], [ 518, -353, 110, 174, 41557 ],
			[ 324, 542, -174, 107, 42171 ], [ -482, 200, -72, -158, 38875 ],
			[ -46, -201, 63, -17, 42847 ], [ -140, -45, 16, -50, 30127 ],
			[ -224, 404, -143, -69, 40316 ], [ 181, -98, 38, 55, 38379 ],
			[ -121, 59, -24, -35, 37783 ], [ -9, -73, 27, -6, 28550 ],
			[ 35, -42, 15, 13, 27300 ], [ 63, -35, 15, 16, 37225 ],
			[ 56, -64, 15, 12, 20459 ], [ 18, -77, 18, 3, 20151 ],
			[ -8, 41, -9, -13, 170984 ], [ 51, 9, -2, 16, 29197 ],
			[ 3425, -2525, , , 1309223 ], [ -2951, 1938, , , 991814 ],
			[ 2117, -704, , , 716770 ], [ 877, -993, , , 416787 ],
			[ -805, 226, , , 554293 ], [ -710, -52, , , 371201 ],
			[ 448, -33, , , 324763 ], [ -217, 111, , , 122237 ],
			[ 224, -55, , , 94370 ], [ -228, 37, , , 287695 ] ];

	唐凯_ecliptic_precession_terms
	// 原數值: [ [ 5540″, -1.98e-4″ ], [ -1608″, -2.06e-4 ] ]
	// 已轉成適用於 Julian century 使用。
	.init = [ [ 5540, -0.0198 ], [ -1608, -0.0206 ] ];
	唐凯_ecliptic_precession_terms.forEach(function(term) {
		// 100: 轉成適用於 Julian century 使用。
		// Julian year (the time reckoned from J2000.0 in years)
		// → Julian century
		term[4] = 100 * TURN_TO_RADIANS / term[4];
	});

	唐凯_precession_terms
	// 原數值: [ [ 6221″, 50″.44766 ], [ 83953″, -8.9e-5″ ] ]
	// 已轉成適用於 Julian century 使用。
	.init = [ [ 6221, 5044.766 ], [ 83953, -0.0089 ] ];
	唐凯_precession_terms.forEach(function(term) {
		// 100: 轉成適用於 Julian century 使用。
		// Julian year (the time reckoned from J2000.0 in years)
		// → Julian century
		term[4] = 100 * TURN_TO_RADIANS / term[4];
	});

	// ------------------------------------------------------------------------------------------------------//
	// 章動 nutation

	var IAU2000B_nutation_offset_Δψ = -0.135,
	//
	IAU2000B_nutation_offset_Δε = 0.388;
	(function() {
		var d = TURN_TO_RADIANS / ONE_DAY_SECONDS / 1e3;
		IAU2000B_nutation_offset_Δψ *= d;
		IAU2000B_nutation_offset_Δε *= d;
	})();

	/**
	 * terms for function nutation()
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Nutation, IAU 2000B model.
	 * https://github.com/kanasimi/IAU-SOFA/blob/master/src/nut00b.c
	 * 
	 * @see http://www.neoprogrammics.com/nutations/nutations_1980_2000b/index.php
	 * 
	 * @inner
	 */
	var IAU2000B_nutation_parameters = [
	// el: Mean anomaly of the Moon. 月亮平近點角
	[ 485868.249036, 1717915923.2178
	// , 31.8792, 0.051635, -0.00024470
	],
	// elp(el'): Mean anomaly of the Sun. 太陽平近點角
	[ 1287104.79305, 129596581.0481
	// , -0.5532, 0.000136, -0.00001149
	],
	// f: Mean argument of the latitude of the Moon. 月亮平升交角距
	[ 335779.526232, 1739527262.8478
	// , -12.7512, -0.001037, 0.00000417
	],
	// d: Mean elongation of the Moon from the Sun. 日月平角距
	[ 1072260.70369, 1602961601.2090
	// , -6.3706, 0.006593, -0.00003169
	],
	// om(Ω): Mean longitude of the ascending node of the Moon.
	// 月亮升交點平黃經
	[ 450160.398036, -6962890.5431
	// , 7.4722, 0.007702, -0.00005939
	] ],

	// 0–4: coefficients of l,l',F,D,Om
	// int nl,nlp,nf,nd,nom;
	// 5–7: longitude sin, t*sin, cos coefficients
	// double ps,pst,pc;
	// 8–10: obliquity cos, t*cos, sin coefficients
	// double ps,pst,pc;
	IAU2000B_nutation_terms = [
			/* 1-10 */
			[ 0, 0, 0, 0, 1, -172064161, -174666, 33386,
			// Astronomical Almanac 2011:
			// Constant of nutation at epoch J2000.0:
			// N = 9.2052331″
			92052331, 9086, 15377 ],
			[ 0, 0, 2, -2, 2, -13170906, -1675, -13696, 5730336, -3015, -4587 ],
			[ 0, 0, 2, 0, 2,
			//
			-2276413, -234, 2796, 978459, -485, 1374 ],
			[ 0, 0, 0, 0, 2, 2074554, 207, -698, -897492, 470, -291 ],
			[ 0, 1, 0, 0, 0,
			//
			1475877, -3633, 11817, 73871, -184, -1924 ], [ 0, 1, 2, -2, 2,
			//
			-516821, 1226, -524, 224386, -677, -174 ],
			[ 1, 0, 0, 0, 0, 711159, 73, -872, -6750, 0, 358 ],
			[ 0, 0, 2, 0, 1, -387298, -367, 380, 200728, 18, 318 ],
			[ 1, 0, 2, 0, 2, -301461, -36, 816, 129025, -63, 367 ],
			[ 0, -1, 2, -2, 2, 215829, -494, 111, -95929, 299, 132 ],

			/* 11-20 */
			[ 0, 0, 2, -2, 1, 128227, 137, 181, -68982, -9, 39 ],
			[ -1, 0, 2, 0, 2, 123457, 11, 19, -53311, 32, -4 ],
			[ -1, 0, 0, 2, 0, 156994, 10, -168, -1235, 0, 82 ],
			[ 1, 0, 0, 0, 1, 63110, 63, 27, -33228, 0, -9 ],
			[ -1, 0, 0, 0, 1, -57976, -63, -189, 31429, 0, -75 ],
			[ -1, 0, 2, 2, 2, -59641, -11, 149, 25543, -11, 66 ],
			[ 1, 0, 2, 0, 1, -51613, -42, 129, 26366, 0, 78 ],
			[ -2, 0, 2, 0, 1, 45893, 50, 31, -24236, -10, 20 ],
			[ 0, 0, 0, 2, 0, 63384, 11, -150, -1220, 0, 29 ],
			[ 0, 0, 2, 2, 2, -38571, -1, 158, 16452, -11, 68 ],

			/* 21-30 */
			[ 0, -2, 2, -2, 2, 32481, 0, 0, -13870, 0, 0 ],
			[ -2, 0, 0, 2, 0, -47722, 0, -18, 477, 0, -25 ],
			[ 2, 0, 2, 0, 2, -31046, -1, 131, 13238, -11, 59 ],
			[ 1, 0, 2, -2, 2, 28593, 0, -1, -12338, 10, -3 ],
			[ -1, 0, 2, 0, 1, 20441, 21, 10, -10758, 0, -3 ],
			[ 2, 0, 0, 0, 0, 29243, 0, -74, -609, 0, 13 ],
			[ 0, 0, 2, 0, 0, 25887, 0, -66, -550, 0, 11 ],
			[ 0, 1, 0, 0, 1, -14053, -25, 79, 8551, -2, -45 ],
			[ -1, 0, 0, 2, 1, 15164, 10, 11, -8001, 0, -1 ],
			[ 0, 2, 2, -2, 2, -15794, 72, -16, 6850, -42, -5 ],

			/* 31-40 */
			[ 0, 0, -2, 2, 0, 21783, 0, 13, -167, 0, 13 ],
			[ 1, 0, 0, -2, 1, -12873, -10, -37, 6953, 0, -14 ],
			[ 0, -1, 0, 0, 1, -12654, 11, 63, 6415, 0, 26 ],
			[ -1, 0, 2, 2, 1, -10204, 0, 25, 5222, 0, 15 ],
			[ 0, 2, 0, 0, 0, 16707, -85, -10, 168, -1, 10 ],
			[ 1, 0, 2, 2, 2, -7691, 0, 44, 3268, 0, 19 ],
			[ -2, 0, 2, 0, 0, -11024, 0, -14, 104, 0, 2 ],
			[ 0, 1, 2, 0, 2, 7566, -21, -11, -3250, 0, -5 ],
			[ 0, 0, 2, 2, 1, -6637, -11, 25, 3353, 0, 14 ],
			[ 0, -1, 2, 0, 2, -7141, 21, 8, 3070, 0, 4 ],

			/* 41-50 */
			[ 0, 0, 0, 2, 1, -6302, -11, 2, 3272, 0, 4 ],
			[ 1, 0, 2, -2, 1, 5800, 10, 2, -3045, 0, -1 ],
			[ 2, 0, 2, -2, 2, 6443, 0, -7, -2768, 0, -4 ],
			[ -2, 0, 0, 2, 1, -5774, -11, -15, 3041, 0, -5 ],
			[ 2, 0, 2, 0, 1, -5350, 0, 21, 2695, 0, 12 ],
			[ 0, -1, 2, -2, 1, -4752, -11, -3, 2719, 0, -3 ],
			[ 0, 0, 0, -2, 1, -4940, -11, -21, 2720, 0, -9 ],
			[ -1, -1, 0, 2, 0, 7350, 0, -8, -51, 0, 4 ],
			[ 2, 0, 0, -2, 1, 4065, 0, 6, -2206, 0, 1 ],
			[ 1, 0, 0, 2, 0, 6579, 0, -24, -199, 0, 2 ],

			/* 51-60 */
			[ 0, 1, 2, -2, 1, 3579, 0, 5, -1900, 0, 1 ],
			[ 1, -1, 0, 0, 0, 4725, 0, -6, -41, 0, 3 ],
			[ -2, 0, 2, 0, 2, -3075, 0, -2, 1313, 0, -1 ],
			[ 3, 0, 2, 0, 2, -2904, 0, 15, 1233, 0, 7 ],
			[ 0, -1, 0, 2, 0, 4348, 0, -10, -81, 0, 2 ],
			[ 1, -1, 2, 0, 2, -2878, 0, 8, 1232, 0, 4 ],
			[ 0, 0, 0, 1, 0, -4230, 0, 5, -20, 0, -2 ],
			[ -1, -1, 2, 2, 2, -2819, 0, 7, 1207, 0, 3 ],
			[ -1, 0, 2, 0, 0, -4056, 0, 5, 40, 0, -2 ],
			[ 0, -1, 2, 2, 2, -2647, 0, 11, 1129, 0, 5 ],

			/* 61-70 */
			[ -2, 0, 0, 0, 1, -2294, 0, -10, 1266, 0, -4 ],
			[ 1, 1, 2, 0, 2, 2481, 0, -7, -1062, 0, -3 ],
			[ 2, 0, 0, 0, 1, 2179, 0, -2, -1129, 0, -2 ],
			[ -1, 1, 0, 1, 0, 3276, 0, 1, -9, 0, 0 ],
			[ 1, 1, 0, 0, 0, -3389, 0, 5, 35, 0, -2 ],
			[ 1, 0, 2, 0, 0, 3339, 0, -13, -107, 0, 1 ],
			[ -1, 0, 2, -2, 1, -1987, 0, -6, 1073, 0, -2 ],
			[ 1, 0, 0, 0, 2, -1981, 0, 0, 854, 0, 0 ],
			[ -1, 0, 0, 1, 0, 4026, 0, -353, -553, 0, -139 ],
			[ 0, 0, 2, 1, 2, 1660, 0, -5, -710, 0, -2 ],

			/* 71-77 */
			[ -1, 0, 2, 4, 2, -1521, 0, 9, 647, 0, 4 ],
			[ -1, 1, 0, 1, 1, 1314, 0, 0, -700, 0, 0 ],
			[ 0, -2, 2, -2, 1, -1283, 0, 0, 672, 0, 0 ],
			[ 1, 0, 2, 2, 1, -1331, 0, 8, 663, 0, 4 ],
			[ -2, 0, 2, 2, 2, 1383, 0, -2, -594, 0, -2 ],
			[ -1, 0, 0, 0, 2, 1405, 0, 4, -610, 0, 2 ],
			[ 1, 1, 2, -2, 2, 1290, 0, 0, -556, 0, 0 ] ];

	/**
	 * terms for function nutation()
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * table 22.A.<br />
	 * 
	 * @see https://github.com/kanasimi/IAU-SOFA/blob/master/src/nut80.c
	 * 
	 * @inner
	 */
	// IAU1980_nutation_parameters 單位是度。
	var IAU1980_nutation_parameters = [
	// 平距角(日月對地心的角距離)：
	// D = 297.85036 + 445267.111480*T - 0.0019142*T² +
	// T³/189474
	[ 297.85036, 445267.111480, -0.0019142, 1 / 189474 ],
	// 太陽（地球）平近點角：
	// M = 357.52772 + 35999.050340*T - 0.0001603*T² -
	// T³/300000
	[ 357.52772, 35999.050340, -0.0001603, -1 / 300000 ],
	// 月球平近點角：
	// M′= 134.96298 + 477198.867398*T + 0.0086972*T² +
	// T³/56250
	[ 134.96298, 477198.867398, 0.0086972, 1 / 56250 ],
	// 月球緯度參數：
	// F = 93.27191 + 483202.017538*T - 0.0036825*T² +
	// T³/327270
	[ 93.27191, 483202.017538, -0.0036825, 1 / 327270 ],
	// 黃道與月球平軌道升交點黃經，從Date黃道平分點開始測量：
	// Ω= 125.04452 - 1934.136261*T + 0.0020708*T² +
	// T³/450000
	[ 125.04452, -1934.136261, 0.0020708, 1 / 450000 ] ],

	// 這些項來自 IAU 1980 章動理論，忽略了係數小於0″.0003的項。
	// https://github.com/kanasimi/IAU-SOFA/blob/master/src/nut80.c
	IAU1980_nutation_terms = [ [ 0, 0, 0, 0, 1, -171996, -1742, 92025, 89 ],
			[ -2, 0, 0, 2, 2, -13187, -16, 5736, -31 ],
			[ 0, 0, 0, 2, 2, -2274, -2, 977, -5 ],
			[ 0, 0, 0, 0, 2, 2062, 2, -895, 5 ],
			[ 0, 1, 0, 0, 0, 1426, -34, 54, -1 ],
			[ 0, 0, 1, 0, 0, 712, 1, -7, 0 ],
			[ -2, 1, 0, 2, 2, -517, 12, 224, -6 ],
			[ 0, 0, 0, 2, 1, -386, -4, 200, 0 ],
			[ 0, 0, 1, 2, 2, -301, 0, 129, -1 ],
			[ -2, -1, 0, 2, 2, 217, -5, -95, 3 ],
			[ -2, 0, 1, 0, 0, -158, 0, 0, 0 ],
			[ -2, 0, 0, 2, 1, 129, 1, -70, 0 ],
			[ 0, 0, -1, 2, 2, 123, 0, -53, 0 ], [ 2, 0, 0, 0, 0, 63, 0, 0, 0 ],
			[ 0, 0, 1, 0, 1, 63, 1, -33, 0 ],
			[ 2, 0, -1, 2, 2, -59, 0, 26, 0 ],
			[ 0, 0, -1, 0, 1, -58, -1, 32, 0 ],
			[ 0, 0, 1, 2, 1, -51, 0, 27, 0 ], [ -2, 0, 2, 0, 0, 48, 0, 0, 0 ],
			[ 0, 0, -2, 2, 1, 46, 0, -24, 0 ],
			[ 2, 0, 0, 2, 2, -38, 0, 16, 0 ], [ 0, 0, 2, 2, 2, -31, 0, 13, 0 ],
			[ 0, 0, 2, 0, 0, 29, 0, 0, 0 ], [ -2, 0, 1, 2, 2, 29, 0, -12, 0 ],
			[ 0, 0, 0, 2, 0, 26, 0, 0, 0 ], [ -2, 0, 0, 2, 0, -22, 0, 0, 0 ],
			[ 0, 0, -1, 2, 1, 21, 0, -10, 0 ], [ 0, 2, 0, 0, 0, 17, -1, 0, 0 ],
			[ 2, 0, -1, 0, 1, 16, 0, -8, 0 ], [ -2, 2, 0, 2, 2, -16, 1, 7, 0 ],
			[ 0, 1, 0, 0, 1, -15, 0, 9, 0 ], [ -2, 0, 1, 0, 1, -13, 0, 7, 0 ],
			[ 0, -1, 0, 0, 1, -12, 0, 6, 0 ], [ 0, 0, 2, -2, 0, 11, 0, 0, 0 ],
			[ 2, 0, -1, 2, 1, -10, 0, 5, 0 ], [ 2, 0, 1, 2, 2, -8, 0, 3, 0 ],
			[ 0, 1, 0, 2, 2, 7, 0, -3, 0 ], [ -2, 1, 1, 0, 0, -7, 0, 0, 0 ],
			[ 0, -1, 0, 2, 2, -7, 0, 3, 0 ], [ 2, 0, 0, 2, 1, -7, 0, 3, 0 ],
			[ 2, 0, 1, 0, 0, 6, 0, 0, 0 ], [ -2, 0, 2, 2, 2, 6, 0, -3, 0 ],
			[ -2, 0, 1, 2, 1, 6, 0, -3, 0 ], [ 2, 0, -2, 0, 1, -6, 0, 3, 0 ],
			[ 2, 0, 0, 0, 1, -6, 0, 3, 0 ], [ 0, -1, 1, 0, 0, 5, 0, 0, 0 ],
			[ -2, -1, 0, 2, 1, -5, 0, 3, 0 ], [ -2, 0, 0, 0, 1, -5, 0, 3, 0 ],
			[ 0, 0, 2, 2, 1, -5, 0, 3, 0 ], [ -2, 0, 2, 0, 1, 4, 0, 0, 0 ],
			[ -2, 1, 0, 2, 1, 4, 0, 0, 0 ], [ 0, 0, 1, -2, 0, 4, 0, 0, 0 ],
			[ -1, 0, 1, 0, 0, -4, 0, 0, 0 ], [ -2, 1, 0, 0, 0, -4, 0, 0, 0 ],
			[ 1, 0, 0, 0, 0, -4, 0, 0, 0 ], [ 0, 0, 1, 2, 0, 3, 0, 0, 0 ],
			[ 0, 0, -2, 2, 2, -3, 0, 0, 0 ], [ -1, -1, 1, 0, 0, -3, 0, 0, 0 ],
			[ 0, 1, 1, 0, 0, -3, 0, 0, 0 ], [ 0, -1, 1, 2, 2, -3, 0, 0, 0 ],
			[ 2, -1, -1, 2, 2, -3, 0, 0, 0 ], [ 0, 0, 3, 2, 2, -3, 0, 0, 0 ],
			[ 2, -1, 0, 2, 2, -3, 0, 0, 0 ] ];

	// ------------------------------------------------------------------------------------------------------//
	// Sun's aberration. 太陽地心黃經光行差修正量。

	/**
	 * constant term of Sun's aberration
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 167–168. chapter 太陽位置計算.
	 * 
	 * If needed with respect to the mean equinox of the date instead of to a
	 * fixed reference frame, the constant term 3548.193 should be replaced by
	 * 3548.330. 如果Δλ須是在Date黃道中的，則應把常數項3548.193換為3548.330
	 * 
	 * The ICRF is a fixed reference frame. The FK5 based on fixed reference
	 * frame of J2000.0?
	 * 
	 * @see http://blog.csdn.net/songgz/article/details/2680144<br />
	 *      通過數以千計的恆星位置，反推出春風點在天球上的位置，我們常說的FK5天球坐標系統就與它有關。
	 * @see https://en.wikipedia.org/wiki/Barycentric_celestial_reference_system<br />
	 *      The orientation of the BCRS/ICRS axes also align within 0.02
	 *      arcsecond of the Earth's mean equator and equinox for the Fifth
	 *      Fundamental Catalog (FK5) J2000.0 epoch.
	 * @see http://aa.usno.navy.mil/faq/docs/ICRS_doc.php<br />
	 *      The orientation of the ICRS axes is consistent with the equator and
	 *      equinox of J2000.0 represented by the FK5, within the errors of the
	 *      latter.
	 * 
	 * @inner
	 */
	var sun_aberration_variation_constant = 3548.193,
	/**
	 * coefficients of Sun's aberration
	 * 
	 * Σ : Σ ([0] * sin ( [1] + [2] τ) )
	 * 
	 * daily variation = sun_aberration_variation_constant + Σ(variation[0]) +
	 * Σ(variation[1])*τ + Σ(variation[2])*τ² + Σ(variation[3])*τ³
	 * 
	 * τ的係數為359993.7、719987或1079981的週期項，與地球離心率相關。<br />
	 * τ的係數為4452671、9224660或4092677的週期項，與月球運動相關。<br />
	 * τ的係數為450369、225184、315560或675553的週期項，與金星攝動相關。<br />
	 * τ的係數為329645、659289、或299296的週期項，與火星攝動相關。
	 * 
	 * @inner
	 */
	sun_aberration_variation = [
			// τ⁰
			[ [ 118.568, 87.5287, 359993.7286 ],
					[ 2.476, 85.0561, 719987.4571 ],
					[ 1.376, 27.8502, 4452671.1152 ],
					[ 0.119, 73.1375, 450368.8564 ],
					[ 0.114, 337.2264, 329644.6718 ],
					[ 0.086, 222.5400, 659289.3436 ],
					[ 0.078, 162.8136, 9224659.7915 ],
					[ 0.054, 82.5823, 1079981.1857 ],
					[ 0.052, 171.5189, 225184.4282 ],
					[ 0.034, 30.3214, 4092677.3866 ],
					[ 0.033, 119.8105, 337181.4711 ],
					[ 0.023, 247.5418, 299295.6151 ],
					[ 0.023, 325.1526, 315559.5560 ],
					[ 0.021, 155.1241, 675553.2846 ] ],
			// τ¹
			[ [ 7.311, 333.4515, 359993.7286 ],
					[ 0.305, 330.9814, 719987.4571 ],
					[ 0.010, 328.5170, 1079981.1857 ] ],
			// τ²
			[ [ 0.309, 241.4518, 359993.7286 ],
					[ 0.021, 205.0482, 719987.4571 ],
					[ 0.004, 297.8610, 4452671.1152 ] ],
			// τ³
			[ [ 0.010, 154.7066, 359993.7286 ] ] ];

	sun_aberration_variation.forEach(function(term) {
		term.forEach(function(sub_term) {
			sub_term[1] *= DEGREES_TO_RADIANS;
			sub_term[2] *= DEGREES_TO_RADIANS;
		});
	});

	// ------------------------------------------------------------------------------------------------------//

	/**
	 * terms for function equinox()
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * chapter 分點和至點.<br />
	 * 
	 * @inner
	 */
	// for years -1000 to 1000
	var equinox_terms_before_1000 = [
	// March equinox, 春分點時刻
	[ 1721139.29189, 365242.13740, 0.06134, 0.00111, -0.00071 ],
	// June Solstice, 夏至點時刻
	[ 1721233.25401, 365241.72562, -0.05323, 0.00907, 0.00025 ],
	// September equinox, 秋分點時刻
	[ 1721325.70455, 365242.49558, -0.11677, -0.00297, 0.00074 ],
	// December Solstice, 冬至點時刻
	[ 1721414.39987, 365242.88257, -0.00769, -0.00933, -0.00006 ] ],
	// for years 1000 to 3000
	equinox_terms_after_1000 = [
	// March equinox, 春分點時刻
	[ 2451623.80984, 365242.37404, 0.05169, -0.00411, -0.00057 ],
	// June Solstice, 夏至點時刻
	[ 2451716.56767, 365241.62603, 0.00325, 0.00888, -0.00030 ],
	// September equinox, 秋分點時刻
	[ 2451810.21715, 365242.01767, -0.11575, 0.00337, 0.00078 ],
	// December Solstice, 冬至點時刻
	[ 2451900.05952, 365242.74049, -0.06223, -0.00823, 0.00032 ] ],
	// 週期項
	equinox_periodic_terms = [
	//
	[ 485, 324.96, 1934.136 ], [ 203, 337.23, 32964.467 ],
			[ 199, 342.08, 20.186 ], [ 182, 27.85, 445267.112 ],
			[ 156, 73.14, 45036.886 ], [ 136, 171.52, 22518.443 ],
			[ 77, 222.54, 65928.934 ], [ 74, 296.72, 3034.906 ],
			[ 70, 243.58, 9037.513 ], [ 58, 119.81, 33718.147 ],
			[ 52, 297.17, 150.678 ], [ 50, 21.02, 2281.226 ],
			[ 45, 247.54, 29929.562 ], [ 44, 325.15, 31555.956 ],
			[ 29, 60.93, 4443.417 ], [ 18, 155.12, 67555.328 ],
			[ 17, 288.79, 4562.452 ], [ 16, 198.04, 62894.029 ],
			[ 14, 199.76, 31436.921 ], [ 12, 95.39, 14577.848 ],
			[ 12, 287.11, 31931.756 ], [ 12, 320.81, 34777.259 ],
			[ 9, 227.73, 1222.114 ], [ 8, 15.45, 16859.074 ] ];

	// 把能先做的做一做，加快運算速度。
	equinox_periodic_terms.forEach(function(terms) {
		terms[1] *= DEGREES_TO_RADIANS;
		terms[2] *= DEGREES_TO_RADIANS;
	});

	// ------------------------------------------------------------------------------------------------------//
	// VSOP87 半解析（semi-analytic）理論 periodic terms

	/**
	 * 這邊僅擷取行星 Earth 地球數值，以計算二十四節氣 (solar terms)。
	 * 
	 * VSOP87_terms.earth[L黃經/B黃緯/R距離] = [L0:[[A,B,C],[A,B,C]]];
	 * 
	 * simplified VSOP87 by Jean Meeus.
	 * 從VSOP87中取出一些主要項(詳見附錄II)，利用它計算得到的太陽位置在-2000到6000年範圍內精度是1"。<br />
	 * 誤差 365.25*24*60*60/360/60/60 = 24.35秒鐘。相當於半分鐘。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * Appendix III 附表3.<br />
	 * http://forums.parallax.com/showthread.php/154838-Azimuth-angle-conversion-from-east-to-west
	 * 
	 * @see http://www.neoprogrammics.com/vsop87/source_code_generator_tool/
	 *      VSOP87B日心黃道球面坐標 Heliocentric LBR - J2000
	 * @see ftp://ftp.imcce.fr/pub/ephem/planets/vsop87/VSOP87B.ear
	 */
	VSOP87_terms.earth = {
		multiplier : 1e-8,
		// 行星 Earth 地球: 日心黃經
		L : [
				[ [ 175347046.0, 0, 0 ], [ 3341656.0, 4.6692568, 6283.07585 ],
						[ 34894.0, 4.6261, 12566.1517 ],
						[ 3497.0, 2.7441, 5753.3849 ],
						[ 3418.0, 2.8289, 3.5231 ],
						[ 3136.0, 3.6277, 77713.7715 ],
						[ 2676.0, 4.4181, 7860.4194 ],
						[ 2343.0, 6.1352, 3930.2097 ],
						[ 1324.0, 0.7425, 11506.7698 ],
						[ 1273.0, 2.0371, 529.691 ],
						[ 1199.0, 1.1096, 1577.3435 ],
						[ 990, 5.233, 5884.927 ], [ 902, 2.045, 26.298 ],
						[ 857, 3.508, 398.149 ], [ 780, 1.179, 5223.694 ],
						[ 753, 2.533, 5507.553 ], [ 505, 4.583, 18849.228 ],
						[ 492, 4.205, 775.523 ], [ 357, 2.92, 0.067 ],
						[ 317, 5.849, 11790.629 ], [ 284, 1.899, 796.298 ],
						[ 271, 0.315, 10977.079 ], [ 243, 0.345, 5486.778 ],
						[ 206, 4.806, 2544.314 ], [ 205, 1.869, 5573.143 ],
						[ 202, 2.458, 6069.777 ], [ 156, 0.833, 213.299 ],
						[ 132, 3.411, 2942.463 ], [ 126, 1.083, 20.775 ],
						[ 115, 0.645, 0.98 ], [ 103, 0.636, 4694.003 ],
						[ 102, 0.976, 15720.839 ], [ 102, 4.267, 7.114 ],
						[ 99, 6.21, 2146.17 ], [ 98, 0.68, 155.42 ],
						[ 86, 5.98, 161000.69 ], [ 85, 1.3, 6275.96 ],
						[ 85, 3.67, 71430.7 ], [ 80, 1.81, 17260.15 ],
						[ 79, 3.04, 12036.46 ], [ 75, 1.76, 5088.63 ],
						[ 74, 3.5, 3154.69 ], [ 74, 4.68, 801.82 ],
						[ 70, 0.83, 9437.76 ], [ 62, 3.98, 8827.39 ],
						[ 61, 1.82, 7084.9 ], [ 57, 2.78, 6286.6 ],
						[ 56, 4.39, 14143.5 ], [ 56, 3.47, 6279.55 ],
						[ 52, 0.19, 12139.55 ], [ 52, 1.33, 1748.02 ],
						[ 51, 0.28, 5856.48 ], [ 49, 0.49, 1194.45 ],
						[ 41, 5.37, 8429.24 ], [ 41, 2.4, 19651.05 ],
						[ 39, 6.17, 10447.39 ], [ 37, 6.04, 10213.29 ],
						[ 37, 2.57, 1059.38 ], [ 36, 1.71, 2352.87 ],
						[ 36, 1.78, 6812.77 ], [ 33, 0.59, 17789.85 ],
						[ 30, 0.44, 83996.85 ], [ 30, 2.74, 1349.87 ],
						[ 25, 3.16, 4690.48 ] ],
				[ [ 628331966747.0, 0, 0 ], [ 206059.0, 2.678235, 6283.07585 ],
						[ 4303.0, 2.6351, 12566.1517 ], [ 425.0, 1.59, 3.523 ],
						[ 119.0, 5.796, 26.298 ], [ 109.0, 2.966, 1577.344 ],
						[ 93, 2.59, 18849.23 ], [ 72, 1.14, 529.69 ],
						[ 68, 1.87, 398.15 ], [ 67, 4.41, 5507.55 ],
						[ 59, 2.89, 5223.69 ], [ 56, 2.17, 155.42 ],
						[ 45, 0.4, 796.3 ], [ 36, 0.47, 775.52 ],
						[ 29, 2.65, 7.11 ], [ 21, 5.34, 0.98 ],
						[ 19, 1.85, 5486.78 ], [ 19, 4.97, 213.3 ],
						[ 17, 2.99, 6275.96 ], [ 16, 0.03, 2544.31 ],
						[ 16, 1.43, 2146.17 ], [ 15, 1.21, 10977.08 ],
						[ 12, 2.83, 1748.02 ], [ 12, 3.26, 5088.63 ],
						[ 12, 5.27, 1194.45 ], [ 12, 2.08, 4694 ],
						[ 11, 0.77, 553.57 ], [ 10, 1.3, 6286.6 ],
						[ 10, 4.24, 1349.87 ], [ 9, 2.7, 242.73 ],
						[ 9, 5.64, 951.72 ], [ 8, 5.3, 2352.87 ],
						[ 6, 2.65, 9437.76 ], [ 6, 4.67, 4690.48 ] ],
				[ [ 52919.0, 0, 0 ], [ 8720.0, 1.0721, 6283.0758 ],
						[ 309.0, 0.867, 12566.152 ], [ 27, 0.05, 3.52 ],
						[ 16, 5.19, 26.3 ], [ 16, 3.68, 155.42 ],
						[ 10, 0.76, 18849.23 ], [ 9, 2.06, 77713.77 ],
						[ 7, 0.83, 775.52 ], [ 5, 4.66, 1577.34 ],
						[ 4, 1.03, 7.11 ], [ 4, 3.44, 5573.14 ],
						[ 3, 5.14, 796.3 ], [ 3, 6.05, 5507.55 ],
						[ 3, 1.19, 242.73 ], [ 3, 6.12, 529.69 ],
						[ 3, 0.31, 398.15 ], [ 3, 2.28, 553.57 ],
						[ 2, 4.38, 5223.69 ], [ 2, 3.75, 0.98 ] ],
				[ [ 289.0, 5.844, 6283.076 ], [ 35, 0, 0 ],
						[ 17, 5.49, 12566.15 ], [ 3, 5.2, 155.42 ],
						[ 1, 4.72, 3.52 ], [ 1, 5.3, 18849.23 ],
						[ 1, 5.97, 242.73 ] ],
				[ [ 114.0, 3.142, 0 ], [ 8, 4.13, 6283.08 ],
						[ 1, 3.84, 12566.15 ] ], [ [ 1, 3.14, 0 ] ] ],
		// 行星 Earth 地球: 日心黃緯
		B : [
				[ [ 280, 3.199, 84334.662 ], [ 102, 5.422, 5507.553 ],
						[ 80, 3.88, 5223.69 ], [ 44, 3.7, 2352.87 ],
						[ 32, 4, 1577.34 ] ],
				[ [ 9, 3.9, 5507.55 ], [ 6, 1.73, 5223.69 ] ] ],
		// 行星 Earth 地球: 行星到太陽的距離, 日地距離, 位置向量（又稱向徑或徑矢 radius vector）
		// https://zh.wikipedia.org/wiki/%E4%BD%8D%E7%BD%AE%E5%90%91%E9%87%8F
		R : [
				[ [ 100013989.0, 0, 0 ], [ 1670700.0, 3.0984635, 6283.07585 ],
						[ 13956.0, 3.05525, 12566.1517 ],
						[ 3084.0, 5.1985, 77713.7715 ],
						[ 1628.0, 1.1739, 5753.3849 ],
						[ 1576.0, 2.8469, 7860.4194 ],
						[ 925.0, 5.453, 11506.77 ], [ 542.0, 4.564, 3930.21 ],
						[ 472.0, 3.661, 5884.927 ], [ 346.0, 0.964, 5507.553 ],
						[ 329.0, 5.9, 5223.694 ], [ 307.0, 0.299, 5573.143 ],
						[ 243.0, 4.273, 11790.629 ],
						[ 212.0, 5.847, 1577.344 ],
						[ 186.0, 5.022, 10977.079 ],
						[ 175.0, 3.012, 18849.228 ],
						[ 110.0, 5.055, 5486.778 ], [ 98, 0.89, 6069.78 ],
						[ 86, 5.69, 15720.84 ], [ 86, 1.27, 161000.69 ],
						[ 65, 0.27, 17260.15 ], [ 63, 0.92, 529.69 ],
						[ 57, 2.01, 83996.85 ], [ 56, 5.24, 71430.7 ],
						[ 49, 3.25, 2544.31 ], [ 47, 2.58, 775.52 ],
						[ 45, 5.54, 9437.76 ], [ 43, 6.01, 6275.96 ],
						[ 39, 5.36, 4694 ], [ 38, 2.39, 8827.39 ],
						[ 37, 0.83, 19651.05 ], [ 37, 4.9, 12139.55 ],
						[ 36, 1.67, 12036.46 ], [ 35, 1.84, 2942.46 ],
						[ 33, 0.24, 7084.9 ], [ 32, 0.18, 5088.63 ],
						[ 32, 1.78, 398.15 ], [ 28, 1.21, 6286.6 ],
						[ 28, 1.9, 6279.55 ], [ 26, 4.59, 10447.39 ] ],
				[ [ 103019.0, 1.10749, 6283.07585 ],
						[ 1721.0, 1.0644, 12566.1517 ], [ 702.0, 3.142, 0 ],
						[ 32, 1.02, 18849.23 ], [ 31, 2.84, 5507.55 ],
						[ 25, 1.32, 5223.69 ], [ 18, 1.42, 1577.34 ],
						[ 10, 5.91, 10977.08 ], [ 9, 1.42, 6275.96 ],
						[ 9, 0.27, 5486.78 ] ],
				[ [ 4359.0, 5.7846, 6283.0758 ], [ 124.0, 5.579, 12566.152 ],
						[ 12, 3.14, 0 ], [ 9, 3.63, 77713.77 ],
						[ 6, 1.87, 5573.14 ], [ 3, 5.47, 18849.23 ] ],
				[ [ 145.0, 4.273, 6283.076 ], [ 7, 3.92, 12566.15 ] ],
				[ [ 4, 2.56, 6283.08 ] ] ]
	};

	// ------------------------------------------------------------------------------------------------------//

	/**
	 * convert_LEA406 使用之行星數據。
	 * 
	 * mean longitudes of major planets.
	 */
	var convert_LEA406_arguments
	// @see ReadMe_Eng.pdf, from build_LEA406.txt
	// all in arcseconds.
	= [
	// [0]: 為配合 fields.
	null, [ 485868.249036, 17179159232.178, 3187.92, 51.635, -2.447 ],
	//
	[ 1287104.793048, 1295965810.481, -55.32, 0.136, -0.1149 ],
	//
	[ 335779.526232, 17395272628.478, -1275.12, -1.037, 0.0417 ],
	//
	[ 1072260.703692, 16029616012.09, -637.06, 6.593, -0.3169 ],
	//
	[ 450160.398036, -69679193.631, 636.02, 7.625, -0.3586 ],
	//
	[ 908103.259872, 5381016286.88982, -1.92789, 0.00639, 0 ],
	//
	[ 655127.28306, 2106641364.33548, 0.59381, -0.00627, 0 ],
	//
	[ 361679.244588, 1295977422.83429, -2.04411, -0.00523, 0 ],
	//
	[ 1279558.798488, 689050774.93988, 0.94264, -0.01043, 0 ],
	//
	[ 123665.467464, 109256603.77991, -30.60378, 0.05706, 0.04667 ],
	//
	[ 180278.79948, 43996098.55732, 75.61614, -0.16618, -0.11484 ],
	//
	[ 1130598.018396, 15424811.93933, -1.75083, 0.02156, 0 ],
	//
	[ 1095655.195728, 7865503.20744, 0.21103, -0.00895, 0 ],
	//
	[ 0, 50288.2, 111.2022, 0.0773, -0.2353 ] ],
	// 將 Amp 轉整數: Amp *= 1e7 (表格中小數7位數)。
	Amp_to_integer = 1e7;

	// ------------------------------------------------------------------------------------------------------//

	/**
	 * 初始化 Saros Series data.
	 * 
	 * @param {Array}saros_starts
	 *            Solar/Lunar Eclipses Saros Series start TT, MUST > 1.5
	 * @param {Integer}offset
	 *            offset of saros index
	 * @param {Array}saros_starts_TT
	 *            Array to put Solar/Lunar Eclipses Saros Series start TT.
	 *            saros_starts_TT[1] = start TT of series 1
	 * 
	 * @returns {Array} [ remainder, saros_index ];
	 * 
	 * @inner
	 */
	function create_saros_index(saros_starts, offset, saros_starts_TT) {
		var saros_data = [];
		saros_starts.forEach(function(TT, index) {
			saros_starts_TT[index += offset] = TT;
			// -1.5: 確保查詢時一定大於底限。因此需要壓低底限。
			saros_data.push([ (TT - 1.5) % saros_days, [ index, TT ] ]);
		});
		saros_data.sort(function(a, b) {
			return a[0] - b[0];
		});
		// console.log(saros_data);

		var remainder = [], saros_index = [];
		saros_data.forEach(function(data) {
			remainder.push(data[0]);
			saros_index.push(data[1]);
		});

		if (false) {
			var min_gap = Infinity;
			remainder.forEach(function(r, index) {
				if (index > 0 && min_gap > r - remainder[index - 1])
					min_gap = r - remainder[index - 1];
			});
			console.log('min gap: ' + min_gap);
			// min gap ≈ 27.7707
		}

		return [ remainder, saros_index ];
	}

	/**
	 * 沙羅週期 The saros is a period of approximately 223 synodic months
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * wikipedia: 6585.3211 , SEsaros.html: 6585.3223
	 * 
	 * 奇數的數字表示發生在接近昇交點的日食，偶數的數字表示發生在接近降交點的日食；但在月食這種數字的搭配是相反的。沙羅序列的編號是以最大食出現，也就是最接近交點的時間來排列的。
	 * 
	 * 任何時間都有大約40個不同的沙羅序列在進行中。 以2008年為例，共有39個日食的沙羅序列在進行中，而月食則有41個序列在進行中。
	 * 
	 * @see https://en.wikipedia.org/wiki/Saros_%28astronomy%29
	 * @see http://eclipse.gsfc.nasa.gov/SEsaros/SEsaros.html
	 */
	var saros_days = 6585.3211,
	// Solar/Lunar Eclipses Saros Series start TT
	// solar_saros[1]: The start TT of Solar Eclipses Saros Series 1
	solar_saros = [], lunar_saros = [],
	// remainder[0] 為依 saros_days, sort 過的 remainder.
	// remainder[1] 為 [ 所指向的 saros series index, start JDN (TT) ]
	//
	// http://eclipse.gsfc.nasa.gov/SEsaros/SEperiodtab4.html
	// http://eclipse.gsfc.nasa.gov/SEsaros/SEsaros0-180.html
	// http://eclipse.gsfc.nasa.gov/SEsaros/SEsaros000.html
	solar_saros_remainder = create_saros_index([ 524207, 541365, 571692,
			562508, 579666, 609994, 534956, 538943, 575856, 573257, 590415,
			620743, 624729, 641887, 672215, 676201, 693358, 723686, 727672,
			744830, 775158, 779144, 783132, 820045, 810860, 748994, 792493,
			789893, 787295, 824208, 834780, 838767, 869095, 886252, 890239,
			927152, 937723, 941710, 978624, 989195, 993182, 1023511, 1034082,
			972215, 1061812, 1006530, 997346, 1021089, 1038246, 1042232,
			1065975, 1089717, 1093704, 1117447, 1141189, 1145176, 1168919,
			1192661, 1196648, 1220391, 1244133, 1234949, 1265278, 1282434,
			1207396, 1217969, 1254882, 1252283, 1262856, 1293183, 1297170,
			1314327, 1344655, 1348641, 1365799, 1396127, 1400113, 1417271,
			1447599, 1445000, 1462158, 1492486, 1456960, 1421435, 1471519,
			1455749, 1466321, 1496649, 1500635, 1511208, 1548121, 1552107,
			1562680, 1599593, 1603579, 1614151, 1644480, 1655051, 1659038,
			1695951, 1693352, 1631485, 1727667, 1672385, 1663201, 1693530,
			1710686, 1714673, 1738416, 1755573, 1766145, 1789888, 1807045,
			1817617, 1841360, 1858517, 1862503, 1892832, 1903403, 1887634,
			1924548, 1921949, 1873252, 1890410, 1914152, 1918139, 1935297,
			1959039, 1963025, 1986768, 2010511, 2014497, 2031655, 2061983,
			2065969, 2083127, 2113455, 2104270, 2108257, 2151756, 2083303,
			2080705, 2124204, 2121604, 2132177, 2162505, 2166491, 2177063,
			2207391, 2217963, 2228535, 2258863, 2269435, 2273422, 2310335,
			2314321, 2311723, 2355222, 2319696, 2284170, 2314499, 2325070,
			2329057, 2352800, 2369957, 2380529, 2404272, 2421429, 2425415,
			2455744, 2472901, 2476887, 2500630, 2517787, 2515188, 2545517,
			2556088, 2487636, 2504794, 2535122, 2525937, 2543095, 2573423,
			2577409, 2594567, 2624895, 2628881, 2646039, 2669781, 2673767,
			2690925, 2721253, 2718654, 2729227, 2759554, 2704272, 2695089,
			2738588, 2729403, 2739975, 2770303, 2774289, 2784862, 2815190 ],
			-13, solar_saros),

	// http://eclipse.gsfc.nasa.gov/LEsaros/LEperiodtab3.html
	// http://eclipse.gsfc.nasa.gov/LEsaros/LEsaroscat.html
	// https://en.wikipedia.org/wiki/List_of_Saros_series_for_lunar_eclipses
	// http://eclipse.gsfc.nasa.gov/LEcat5/LE-1999--1900.html
	lunar_saros_remainder = create_saros_index([ 534086, 544657, 542059,
			585557, 582958, 507921, 538249, 555406, 552807, 576550, 600292,
			604279, 628022, 645179, 655751, 679494, 703236, 707223, 730966,
			754708, 752109, 782438, 799594, 783825, 754885, 824725, 762858,
			773431, 810344, 807744, 824902, 855230, 859216, 876374, 906702,
			910688, 927846, 958174, 962160, 979318, 1009646, 1007047, 1017619,
			1054532, 979494, 976896, 1020395, 1017795, 1028368, 1058696,
			1062682, 1073254, 1110168, 1114154, 1131312, 1161640, 1165626,
			1176198, 1213112, 1217098, 1221085, 1257998, 1255399, 1186947,
			1283129, 1227846, 1225248, 1255576, 1272733, 1276720, 1307048,
			1317620, 1328192, 1358520, 1375677, 1379664, 1409992, 1420563,
			1424550, 1461464, 1465450, 1436510, 1493180, 1457654, 1435299,
			1452457, 1476199, 1480185, 1503929, 1527671, 1531657, 1548815,
			1579143, 1583129, 1600287, 1624029, 1628016, 1651759, 1675501,
			1672902, 1683475, 1713802, 1645350, 1649337, 1686250, 1683651,
			1694223, 1731137, 1735123, 1745695, 1776023, 1786595, 1797167,
			1827495, 1838067, 1848639, 1878967, 1882953, 1880355, 1923854,
			1881742, 1852802, 1889716, 1893702, 1897689, 1928017, 1938589,
			1942576, 1972904, 1990060, 1994047, 2024376, 2034947, 2045519,
			2075848, 2086419, 2083821, 2120734, 2124720, 2062853, 2086597,
			2103753, 2094569, 2118312, 2142055, 2146041, 2169784, 2186941,
			2197513, 2214671, 2238413, 2242399, 2266143, 2289885, 2287286,
			2311029, 2334771, 2292660, 2276891, 2326975, 2304620, 2308607,
			2345521, 2349507, 2360079, 2390407, 2394393, 2411551, 2441879,
			2445865, 2456438, 2486766, 2490752, 2501324, 2538237, 2529053,
			2473772, 2563368, 2508086, 2505487, 2542401, 2546387, 2556959,
			2587288, 2597859, 2601846, 2632174, 2649331, 2653318, 2683646,
			2694218, 2698204, 2728533, 2739104, 2683823, 2740493, 2724723,
			2708953, 2732696, 2749853, 2753840, 2777583, 2801325, 2805311 ],
			-20, lunar_saros);

	// ------------------------------------------------------------------------------------------------------//

	// all 1325.55: T = k / 1325.55
	// the time of the mean perigee or apogee
	// 計算平近點或遠點時刻
	var lunar_perigee_apogee_T = [ 2451534.6698, 27.55454989 * 1325.55,
			-0.0006691, -0.000001098, 0.0000000052 ],
	// Moon's mean elongation at time JDE:
	// T 時刻的月亮平距角：
	lunar_perigee_apogee_D = [ 171.9179, 335.9106046 * 1325.55, 0.0100383,
			-0.00001156, 0.000000055 ].map(degrees_to_radians),
	// Sun's mean anomaly:
	// 太陽平近點角：
	lunar_perigee_apogee_M = [ 347.3477, 27.1577721 * 1325.55, -0.0008130,
			-0.0008130 ].map(degrees_to_radians),
	// Moon's argument of latitude:
	// 月亮緯度參數：
	lunar_perigee_apogee_F = [ 316.6109, +364.5287911 * 1325.55, -0.0125053,
			-0.0000148 ].map(degrees_to_radians),
	/**
	 * 月亮的近地點 perigee 和遠地點 apogee 之 coefficients 數據 for function
	 * lunar_perigee_apogee()。
	 * 
	 * Reference 資料來源/資料依據:<br />
	 * Jean Meeus, Astronomical Algorithms, 2nd Edition. 《天文算法》2版<br />
	 * p. 355. Chapter 50 Perigee and apogee of the Moon<br />
	 * 
	 * @see https://github.com/helixcn/skycalc/blob/master/src/AAMoonPerigeeApogee.cpp
	 */
	perigee_coefficients_JD = [
	// 近地點 JD 修正量係數。
	[ 2, , , -1.6769 ], [ 4, , , .4589 ], [ 6, , , -.1856 ], [ 8, , , .0883 ],
			[ 2, -1, , -.0773, .00019 ], [ , 1, , .0502, -.00013 ],
			[ 10, , , -.0460 ], [ 4, -1, , .0422, -.00011 ],
			[ 6, -1, , -.0256 ], [ 12, , , .0253 ], [ 1, , , .0237 ],
			[ 8, -1, , .0162 ], [ 14, , , -.0145 ], [ , , 2, .0129 ],
			[ 3, , , -.0112 ], [ 10, -1, , -.0104 ], [ 16, , , .0086 ],
			[ 12, -1, , .0069 ], [ 5, , , .0066 ], [ 2, , 2, -.0053 ],
			[ 18, , , -.0052 ], [ 14, -1, , -.0046 ], [ 7, , , -.0041 ],
			[ 2, 1, , .0040 ], [ 20, , , .0032 ], [ 1, 1, , -.0032 ],
			[ 16, -1, , .0031 ], [ 4, 1, , -.0029 ], [ 9, , , .0027 ],
			[ 4, , 2, .0027 ], [ 2, -2, , -.0027 ], [ 4, -2, , .0024 ],
			[ 6, -2, , -.0021 ], [ 22, , , -.0021 ], [ 18, -1, , -.0021 ],
			[ 6, 1, , .0019 ], [ 11, , , -.0018 ], [ 8, 1, , -.0014 ],
			[ 4, , -2, -.0014 ], [ 6, , 2, -.0014 ], [ 3, 1, , .0014 ],
			[ 5, 1, , -.0014 ], [ 13, , , .0013 ], [ 20, -1, , .0013 ],
			[ 3, 2, , .0011 ], [ 4, -2, 2, -.0011 ], [ 1, 2, , -.0010 ],
			[ 22, -1, , -.0009 ], [ , , 4, -.0008 ], [ 6, , -2, .0008 ],
			[ 2, 1, -2, .0008 ], [ , 2, , .0007 ], [ , -1, 2, .0007 ],
			[ 2, , 4, .0007 ], [ , -2, 2, -.0006 ], [ 2, 2, -2, -.0006 ],
			[ 24, , , .0006 ], [ 4, , -4, .0005 ], [ 2, 2, , .0005 ],
			[ 1, -1, , -.0004 ] ],
	//
	perigee_coefficients_parallax = [
	// 近地點赤道地平視差修正量係數。
	[ , , , 3629.215 ], [ 2, , , 63.224 ], [ 4, , , -6.990 ],
			[ 2, -1, , 2.834, -.0071 ], [ 6, , , 1.927 ], [ 1, , , -1.263 ],
			[ 8, , , -.702 ], [ , 1, , .696, -.0017 ], [ , , 2, -.690 ],
			[ 4, -1, , -.629, .0016 ], [ 2, , -2, -.392 ], [ 10, , , .297 ],
			[ 6, -1, , .260 ], [ 3, , , .201 ], [ 2, 1, , -.161 ],
			[ 1, 1, , .157 ], [ 12, , , -.138 ], [ 8, -1, , -.127 ],
			[ 2, , 2, .104 ], [ 2, -2, , .104 ], [ 5, , , -.079 ],
			[ 14, , , .068 ], [ 10, -1, , .067 ], [ 4, 1, , .054 ],
			[ 12, -1, , -.038 ], [ 4, -2, , -.038 ], [ 7, , , .037 ],
			[ 4, , 2, -.037 ], [ 16, , , -.035 ], [ 3, 1, , -.030 ],
			[ 1, -1, , .029 ], [ 6, 1, , -.025 ], [ , 2, , .023 ],
			[ 14, -1, , .023 ], [ 2, 2, , -.023 ], [ 6, -2, , .022 ],
			[ 2, -1, -2, -.021 ], [ 9, , , -.020 ], [ 18, , , .019 ],
			[ 6, , 2, .017 ], [ , -1, 2, .014 ], [ 16, -1, , -.014 ],
			[ 4, , -2, .013 ], [ 8, 1, , .012 ], [ 11, , , .011 ],
			[ 5, 1, , .010 ], [ 20, , , -.010 ] ],
	//
	apogee_coefficients_JD = [
	// 遠地點 JD 修正量係數。
	[ 2, , , .4392 ], [ 4, , , .0684 ], [ , 1, , .0456, -.00011 ],
			[ 2, -1, , .0426, -.00011 ], [ , , 2, .0212 ], [ 1, , , -.0189 ],
			[ 6, , , .0144 ], [ 4, -1, , .0113 ], [ 2, , 2, .0047 ],
			[ 1, 1, , .0036 ], [ 8, , , .0035 ], [ 6, -1, , .0034 ],
			[ 2, , -2, -.0034 ], [ 2, -2, , .0022 ], [ 3, , , -.0017 ],
			[ 4, , 2, .0013 ], [ 8, -1, , .0011 ], [ 4, -2, , .0010 ],
			[ 10, , , .0009 ], [ 3, 1, , .0007 ], [ , 2, , .0006 ],
			[ 2, 1, , .0005 ], [ 2, 2, , .0005 ], [ 6, , 2, .0004 ],
			[ 6, -2, , .0004 ], [ 10, -1, , .0004 ], [ 5, , , -.0004 ],
			[ 4, , -2, -.0004 ], [ , 1, 2, .0003 ], [ 12, , , .0003 ],
			[ 2, -1, 2, .0003 ], [ 1, -1, , -.0003 ] ],
	//
	apogee_coefficients_parallax = [
	// 遠地點赤道地平視差修正量係數。
	[ , , , 3245.251 ], [ 2, , , -9.147 ], [ 1, , , -.841 ], [ , , 2, .697 ],
			[ , 1, , -.656, .0016 ], [ 4, , , .355 ], [ 2, -1, , .159 ],
			[ 1, 1, , .127 ], [ 4, -1, , .065 ], [ 6, , , .052 ],
			[ 2, 1, , .043 ], [ 2, , 2, .031 ], [ 2, , -2, -.023 ],
			[ 2, -2, , .022 ], [ 2, 2, , .019 ], [ , 2, , -.016 ],
			[ 6, -1, , .014 ], [ 8, , , .010 ] ];

	// ---------------------------------------------------------------------------------------------------------------------------------------//
	// export.

	// ---------------------------------------

	return (_// JSDT:_module_
	);
}
