图中S是太阳的球心,E是地球的质心,M是月球的质心,O是全影影锥锥点,re是地球半径,rm是月球半径。thetaE是从O点观测的地球半径的张角,thetaM是从O点观测的月球半径的张角。thetaEM(∠EOM)、thetaE、thetaM可以利用向量OE、OM和地球半径re、月球半径rm计算出来。　初亏,月球的边缘蹭到地球全影影锥外沿,此时thetaEM=thetaE+thetaM。　食既,月球的边缘蹭到地球全影影锥内沿,此时thetaEM=thetaE-thetaM　食甚,从O点看月球和地球,二者夹角达到最小值,即∠EOM最小时刻食甚。　生光,条件同食既。　复圆,条件初亏。　下面程序里,令a=thetaEM-thetaE-thetaM　b=thetaE-thetaEM-thetaM　初亏之前复圆之后:a>0,初亏之后复圆之前(月食期间):a0　食甚:thetaEM最小　根据这三个几何条件就可以求出月食期间5个阶段的时间。　月食的计算还需要考虑光行时的问题,由于光速有限,太阳发出的光不会立即到达地球,大概是8分钟左右,在这个过程中,日地的相对位置已经发生了改变,而ephemeris函数给出的是即时(函数里给的时间)的日地位置,实际上我们需要的是8分钟前的太阳相对于此刻地球的位置,其实地球到月亮也给需要1秒多的时间,也就是说月食是指八分钟前的太阳发出的光被此刻的地球遮挡,1秒后的月亮进入了该阴影区域被食的现象。实际要计算太阳发出光时候的位置需要迭代计算,这和GPS定位时计算卫星位置是相似的,为了简单起见,也可以直接使用AU除以光速来得到光行时,对最终结果影响不大。　下面分别使用novas库和skyfield库计算月食,后者算法更完善,且在不同操作系统都可以运行。　1.novas　#!/usr/bin/env　python3　#　-*-　coding:　utf-8　-*-　"""　Created　on　Sun　Dec　9　15:32:11　2018　@author:　wpf　"""　#待解决:(1)光行时的迭代,(2)地球形状的考虑,(3)地球上能看到的区域,(4)食分的计算　#/Users/wpf/anaconda3/lib/python3.7/site-packages/novas/compat/compat.py　from　novas　import　compat