65.9K
CodeProject 正在变化。 阅读更多。
Home

时间方程

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.98/5 (92投票s)

2017年2月2日

GPL3

27分钟阅读

viewsIcon

51562

downloadIcon

1646

或者为什么一年中最短的一天不是最早的日落?

引言

如果你住在北半球,那么你肯定会享受现在,2月初,白天已经明显变长了。最短的一天就在几周前(12月21日),但太阳已经比那个黑暗的日子晚了将近一个小时才落下!

我猜大多数人会认为一年中最短的一天也是日出最晚和日落最早的一天。这听起来最自然。我也是这么认为的,直到我更详细地查看了日出和日落时间。令我大吃一惊的是,最早的日落发生在12月12日,而最晚的日出发生在12月30日!

原因很简单,但并不明显:12月的日子比24小时长30秒!这种现象被称为“时间方程”,万维网上有很多关于它的文章,但不幸的是,没有一篇能帮助我真正理解“为什么”,所以我写了这个3D日月模拟,根据各种参数计算日出和日落时间。

背景

乍一看,12月的一天——或任何其他一天——不正好持续24小时可能令人惊讶。一天的长度应该由地球自转的速度决定,而这不应该全年变化!

事实上,地球自转的速度非常稳定,地球完成一次完整的自转大约需要23小时56分钟。但是地球必须再多旋转一点才能结束一天,因为它在这段时间内还绕太阳移动了大约一度。你可以在下面来自维基百科的图片中看到这种效应

事实上,正是这种额外的旋转导致了问题!根据地球的位置和方向,有时完成一个太阳日需要超过4分钟,有时则不到4分钟。

当我们的祖先决定将连续两个正午之间的时间分成24小时时,他们没有原子钟之类的东西。我猜他们甚至不在乎分钟或秒。如果他们必须安排一次会议,那可能就是“我们十点钟见面”之类的。那时真是快乐时光!

如果12月的日子正好是24小时呢?

嗯,世界就会像我们预期的那样:在12月初,太阳会比前一天晚一分钟升起,早一分钟落下。在12月12日,差异会减少到半分钟,在最短的一天12月21日,日出和日落时间之间将不再有任何差异。

从那天起,差异再次增长,但方向相反。所以在12月底,太阳会比前一天早半分钟升起,晚半分钟落下。

额外30秒的影响是什么?

首先,这意味着太阳比前一天晚30秒到达天空的某个位置。因此,如果太阳在某天12:00:00正好在正南方,那么它将在第二天12:00:30到达相同的位置。日出和日落也是如此。一切都以相同的30秒量移动。

如果我们将这种偏移应用于我们在上一节中看到的差异,我们就会得到这个

在12月初,太阳比前一天**晚1.5分钟升起**,但**早0.5分钟落下**。

在12月12日,它**晚一分钟升起**,但**不再早落下**。

在12月21日,它**晚半分钟升起**并**晚半分钟落下**(因此没有净变化)。

在12月底,它**不再早升起**,但**晚一分钟落下**。

那么我们来庆祝12月13日吧!

因为这是太阳比前一天晚落下的第一天!即使差异只有2秒,这无疑是一个新的、更光明时代的开始。

但是如果每一天都比24小时长呢?

嗯,那就不好了!那意味着迟早太阳的位置会与我们的时钟完全不同步。所以当太阳在正午位置时,我们的时钟会显示下午、晚上甚至晚上!由于我们没有经历过如此奇怪的事情,所以一定有什么东西可以弥补12月较长的一天。

事实上,在春天和秋天,白天比24小时短,而在夏天,它们又稍微长一点!

最后,如果我们将这种现象观察一年以上,我们会发现连续两个正午之间的时间围绕一个平均值周期性地变化。而这个值正好是24小时!

宇宙中有什么东西会关心我们的时钟和它们24小时的精确度,这难道不是魔法吗?

当然不是,因为不是地球关心那个时间,而是我们定义了24小时作为两个正午之间的平均时间跨度!

那么为什么每天不正好是24小时呢?

有两个原因

  1. 地球绕太阳的轨道不是一个完美的圆形,而是一个椭圆形
  2. 地球的自转轴不垂直于其轨道平面

根据开普勒行星运动定律,行星的轨道是椭圆,太阳位于其中一个焦点上。这意味着行星有时比其他时候更靠近太阳。这也意味着行星在这些时候绕太阳运行得更快。

如果你看这篇文章开头的图片,就会清楚,如果行星在自转一周后移动到位置2之外的位置,它需要进行更多的额外旋转,直到太阳再次回到正午位置。

地球在1月3日到达离太阳最近的位置(尽管夏季比冬季热)。如果地球的自转轴垂直于其轨道,那么那时的日子将比24小时长8秒。但在夏季,当地球离太阳更远时,日子将短8秒,而在春季和秋季之间,有两次日子正好是24小时。

这是容易的部分。地球绕太阳的速度周期性变化,冬季最大,夏季最小,这使得日子变长变短。

不那么容易的部分是地球所谓的倾斜度或轴倾斜的影响,即地球的自转轴不垂直于其绕太阳的轨道。存在一个约23度的角度,这最主要导致了我们的季节,但也导致我们的正午到正午的时间间隔每年有两个最大值和两个最小值。

如果我们忽略偏心率,并假设地球的轨道是完美的圆形,那么它绕太阳的速度全年都相同,那么根据这种倾斜度,冬季和夏季的日子将比24小时长20秒,而春季和秋季的日子将短20秒。

总而言之,这两种效应加起来就是我们在这里看到的,同样来自维基百科

时间方程的第二个贡献(倾斜度的影响)真的很难用语言解释,这就是模拟发挥作用的地方。

日月系统模拟

模拟很棒!它们有助于理解对我们人类而言太大、太小、太快或太慢的事物。就我们的问题而言,事物太大(太阳与地球之间的距离约为1.5亿公里)且太慢(我们必须等待24小时才能测量两次日出时间之间的差异)。

但是,在进行模拟时,我们可以选择适合我们世界(比如我们电脑的屏幕)的模型,并且我们可以选择时间流逝的速度(例如,24小时在10秒内)。我们可以玩弄影响我们正在研究的各种参数,并且我们可以一遍又一遍地重复相同的模拟,直到我们理解它。

但只有当我们使用的模型正确时,模拟才能给我们真实的答案。所以从正确的模型开始至关重要。模型过于复杂无济于事,但过于简单肯定也不好。介于两者之间听起来是对的。但确切地说在哪里呢?

我们想实现什么?

我们希望我们的模拟能够以至少一秒的精度显示一年中每一天的日出、正午和日落时间。以下参数需要可调:地球自转轴的**倾斜度**、地球轨道的**偏心率**和地球上观测者的**纬度**。

我们不关心绝对值是否与真实值匹配(有一些网站可以用来计算日出和日落时间,例如伦敦或地球上任何其他地方)。但重要的是,两个值之间的差异与真实差异相似。

地球模型

尽管有些人仍然认为地球是扁平的圆盘,但让我们假设它是一个近乎完美的球体,以近乎圆形的轨道绕太阳运行。所以我们从地球是一个完美的球体,轨道是一个完美的圆形开始。我们只需要确保轨道有一个小的偏心率,这最终导致全年速度可变。

地球以非常恒定的方式自转。完成一次自转需要23小时56分4.1秒,因此角速度(弧度/秒)为

double wEarth = MathUtils.PIx2 / MathUtils.ToSeconds(0, 23, 56, 4.1); //--- sidereal day

我们还可以指定地球绕太阳公转的平均角速度:完成一次公转需要365天6小时9分9.54秒。换句话说

double wSun = MathUtils.PIx2 / MathUtils.ToSeconds(365, 6, 9, 9.54); //--- sidereal year

请注意,`wSun` 并不表示太阳自转的角速度,而是表示地球绕太阳公转的平均角速度!如果添加以下声明...

public double Latitude = 51;
public double Obliquity = 23.44;
public double Eccentricity = 0.0167;
double oneDay = MathUtils.ToSeconds(1, 0, 0, 0);

...我们可以编写一个方法,根据`time`值(以秒为单位)计算地球的位置和自转,如下所示

public void Update()
{
    //--- Update earth rotation around itself
    double angle = MathUtils.ToDegrees(wEarth * time);
    EarthRotation = new Quaternion(Math3D.UnitZ, angle);

    //--- Update axial tilt
    AxialTilt = new Quaternion(Math3D.UnitY, -Obliquity);

    //--- Update earth rotation angle around sun
    angle = wSun * time;
    EarthAngle = angle - 2 * Eccentricity * Math.Sin(angle - 15 * wSun * oneDay);

    //--- Update earth position
    EarthPosition = new Point3D(3 * Math.Cos(EarthAngle), 3 * Math.Sin(EarthAngle), 0);
}

第一个四元数(`EarthRotation`)表示地球根据时间自转了多少,而第二个四元数(`AxialTilt`)仅表示恒定的倾斜度。

地球绕太阳运行时角度的计算是一个两步过程:首先根据平均角速度`wSun`计算角度。然后对该角度进行修正。此修正考虑了轨道是椭圆形,近日点在1月3日,远日点在半年后。此近似值适用于小偏心率,并取自此处

现在`EarthAngle`已知,我们可以计算地球在笛卡尔坐标系中的位置。我们可以自由选择一个使我们计算方便的坐标系,因此我们选择xy平面为黄道面,即地球轨道平面。太阳将位于原点。

地球位置计算中的因子3有些随意。它对日出或日落时间没有影响。我选择这个值是为了使地球移动的3D模型(半径为1的球体)看起来正常。

关于坐标轴

如果在上面的`Update()`方法中选择`time`值为`0`,所有结果角度都将为`0`,地球将位于`(3, 0, 0)`,即正x轴上的某个位置。地球的自转轴总是围绕y轴倾斜-23度。因此,在时间为0时,北极正好倾斜向原点,即太阳。这正是夏季的情况。

因此,我们全局坐标系的x轴是冬夏轴,而y轴是秋春轴。

设置观察者位置

日出和日落时间主要取决于观察者的纬度。如果你曾到过赤道附近的熱帶地區,你肯定会注意到太陽幾乎總是在同一時間升起和落下:早上6點日出,晚上6點日落。每天如此。全年如此!

相反,生活在极地地区的人们在夏季有不间断的白昼(太阳永不落下),在冬季有不间断的黑暗(太阳永不升起)。

我们将从纬度为51度的观察者开始模拟,这可以是伦敦。我们并不真正关心观察者的经度。当然,它应该保持不变,我们以一种方式选择它,即当“时间”为零(即地球处于精确的夏季位置)时,我们观察者的当地时间是午夜。

当`time = 0`时情况如下

地球位于正红色x轴上的某个位置,其自转轴朝向太阳倾斜,观测者(51°平行线上的蓝色点)面向黑夜。

然而它在移动!

当模拟启动时,后台线程中会进入一个循环,将`time`值增加1/100秒(此值可调),然后调用上面的`Update()`方法。如果模拟时间过去一秒,代码会检查四个条件

  1. 太阳是否升过地平线?
  2. 太阳是否达到正午位置?
  3. 太阳是否落到地平线以下?
  4. 太阳是否达到午夜位置?

如果其中一个条件为`true`,则存储观察到的`time`值,以与下一天的相应值进行比较。

当后台线程尽可能快地更新地球的核心状态值时,UI线程会在30毫秒的计时器方法中获取这些值,并更新相应3D模型对象的位置和旋转属性。

30毫秒的UI更新应该足够快,以确保流畅的UI体验,但它也应该足够慢,以便为我们的计算机提供足够的资源来执行检查上述四个条件所需的步骤。

数学

上述每个问题的答案都不能一蹴而就。由于我们的模拟是按一定时间步长运行的,我们将无法识别太阳“击中”地平线的确切时间。我们只能识别太阳在第n步时“高于”地平线,而在第n+1步时“低于”地平线。但如果我们知道这两个时间值,我们就可以通过简单的线性插值计算出精确的“击中”时间。

我们首先需要知道的是在特定时间观察者在全局坐标系中的位置。有了这个,我们就可以画一条假想的线到太阳的位置(它总是我们坐标系的原点),并判断它是在地平线之下还是之上,或者是在所谓的子午线(标记正午位置的南向)的左边还是右边。

观察者在全局坐标系中的位置

计算观测者位置非常容易,如果我们采用3D库的相同方法:使用变换矩阵!如果我们知道地球的变换矩阵,我们只需调用`earthMatrix.Transform()`就可以将点从地球坐标系变换到全局坐标系。

再次构建此矩阵非常简单,因为上面的`Update()`方法提供了我们所需的一切。在正式这样做之前,让我们玩一个假想的构建套件。我们的地球是一个半径为1的小球,目前位于全局坐标系的原点。我们需要应用三个变换,使这个球体在特定时间表示地球

  1. 绕z轴旋转球体以显示正确的自旋状态
  2. 绕y轴旋转球体以显示正确的轴倾斜
  3. 将球体平移到正确的xy坐标

代码看起来是这样的

Matrix3D earthMatrix = new Matrix3D();
earthMatrix.Rotate(EarthRotation);
earthMatrix.Rotate(AxialTilt);
earthMatrix.Translate((Vector3D)EarthPosition);

请记住,`Update()`方法计算所需的量`EarthRotation`、`AxialTilt`和`EarthPosition`。有了这个矩阵,我们可以通过调用`earthMatrix.Transform(Point3D pt)`将点从地球系统转换为全局系统。

所以剩下的唯一事情就是计算观察者在地球坐标系中的位置。我们可以用另一个变换矩阵来做这件事。让我们再次回到我们的假想建筑套件。我们需要对目前位于地球中心的观察者应用哪些变换?

  1. 将观测者位置平移到地球表面
  2. 将观察者位置旋转到所需纬度

由于我们的地球模型半径为1,代码如下所示

Matrix3D locationMatrix = new Matrix3D();
locationMatrix.Translate(new Vector3D(1, 0, 0));
locationMatrix.Rotate(new Quaternion(Math3D.UnitY, -Latitude));

如果我们将这个矩阵与地球的变换矩阵结合起来(通过简单地将它们相乘),我们就可以得到一个将点从观察者坐标系变换到全局坐标系的矩阵。由于我们的观察者位于其自身系统的中心,即点`(0,0,0)`处,其全局坐标是

Point3D location = (locationMatrix * earthMatrix).Transform(new Point3D(0, 0, 0));

所以现在我们知道观察者在全局坐标系中的位置,我们可以执行下一步。

计算太阳相对于地平线的位置

要回答太阳是否在地平线之上或之下,请看这张图

地球位置标记为E,观测者位于L。Z是天空中直接位于观测者头顶上方的点。它被称为天顶。它的方向垂直于由H表示的棕色线所示的水平面。

天顶方向立即帮助我们识别太阳是否可见。如果天顶方向和太阳方向之间的角度小于90度,则太阳在地平线之上可见。否则,如果角度大于90度,则太阳在地平线之下不可见。

所以我们只需要知道指向太阳的向量和指向天顶的向量之间的角度。这可以通过使用两个向量的点积手动完成,但是.NET库已经提供了一些方便的方法。但首先,我们需要计算这两个向量!

天顶方向由 L - E 给出,太阳方向简单地是 -E。后者听起来是错误的,因为在我们的模型中,指向太阳的方向应该是 S - L,或者简单地是 -L,因为太阳位于原点,但在这种情况下,我们的模型过于简单。

这个模型中地球半径与太阳距离的关系非常错误,如果我们通过 S - L 计算太阳方向,我们就会做错。实际上,我们可以假设太阳无限远(在原点后面),并且所有来自太阳的光线都平行地射向地球,最终导致 -E 作为太阳的方向。

所以计算太阳和天顶之间角度的代码是这样的

Vector3D dirSun = -(Vector3D)EarthPosition;
Vector3D zenith = location - EarthPosition;
double angle = Vector3D.AngleBetween(dirSun, zenith);

识别日出和日落时间

在模拟过程中观察太阳和天顶之间的角度可以识别日出和日落

  1. 如果前一步的角度大于90°,当前一步的角度小于90°,则发生了日出
  2. 如果前一步的角度小于90°,当前一步的角度大于90°,则发生了日落

在这两种情况下,我们都想找出角度恰好为90°的时间。这是一个简单的线性插值问题,由于上述两次检查之间的时间步长恰好为一秒,因此计算校正时间值的代码可以简化为

double corrTime = time - (angle - 90) / (angle - oldAngle);

其中`time`是实际时间,`angle`是实际角度,`oldAngle`是前一步的角度。

那中午呢?

要确定正午的时间,我们需要确定正午的含义。更具体地说,**太阳正午**的含义。

用我简单的话来说,太阳正午是指太阳在其每日从东方某个升起点到西方某个落下点的路线上,穿过正南方向的时候。至少在我们的北半球是这样。

对于地球上的每个观测者来说,只有一个正南方向,太阳要么在这个方向的左边(正午之前),要么在这个方向的右边(正午之后)。我们可以通过在天空中画一个假想的半圆盘来形象化这个方向,它从北极开始,穿过观测者的天顶,止于南极。

好吧,这听起来可能令人困惑,所以请看这个

希望这个半圆盘现在清楚了。地球表面的小绿点是我们在51°的观察者。请注意,半圆盘绕地球移动的方式与观察者相同(从北极向下看是逆时针方向)。我们在绕极轴旋转时带着我们的南方向!另请注意,我在上图中将轴倾斜设置为零,仅仅是为了更清晰的说明。

这是我对正午的定义:正午时,半圆盘穿过太阳,或者换句话说,太阳穿过我们的半圆盘。因此,当旋转的半圆盘击中太阳中心时,就是正午。

这个半圆盘的名字是**子午线**,它来自拉丁词**meridies**,意思是**中午**。顺便说一句,这就是盎格鲁-美洲国家AM和PM的含义:正午之前,太阳在子午线的左边,即拉丁语中的**ante meridiem**(AM),正午之后,太阳在子午线的右边,即**post meridiem**(PM)。

你可以在这里看到子午线的作用

识别正午时间

现在我们确定了正午的定义,如果我们观察以下情况,我们就能够计算出精确的正午时间

  1. 在当前步骤,太阳位于子午线右侧
  2. 在之前的步骤,太阳位于子午线左侧

那么“左”和“右”是什么意思呢?

借助解析几何,我们会发现“左”和“右”都指的是物体到某个平面的距离。左表示负距离,右表示正距离。我们所说的平面就是子午线。那么我们如何计算太阳到子午线的视距离呢?

这里仍然是向量的点积起了作用。第一个向量当然是太阳的方向(我们已经有了),第二个向量是子午线的法向量,即垂直于子午线的向量。我们可以在倒数第二张图中看到它的方向:它是H - L。

如果太阳在正午位置,那么H - L垂直于太阳方向,点积为零。在任何其他情况下,点积要么是正数,要么是负数。

要计算法向量,我们回到未变换的地球。请记住,未变换的地球只是一个半径为1的球体,位于坐标系的原点,极轴指向z方向。观察者位于`(1, 0, 0)`,因此子午线在这种情况下只是xz平面。因此,该平面的法向量只是y方向,即向量`(0, 1, 0)`。

因此,对于特定`time`值下的法向量计算,我们只需找出地球的y方向在变换后发生了什么。但这很容易做到,因为我们已经有了地球的变换矩阵。如果我们知道变换后的y方向,我们必须将其从地球当前位置中减去,这就是所需的法向量。

所以计算太阳到子午线的距离的代码是这样的

Point3D earthUnitY = earthMatrix.Transform(new Point3D(0, 1, 0));
Vector3D normalOfMeridian = EarthPosition - earthUnitY;
double distance = Vector3D.DotProduct(normalOfMeridian, dirSun);

`dirSun`是否为单位向量无关紧要,因为我们只关注符号的变化。

结果发现,上面的`distance`也有助于我们识别午夜的时间

  1. 如果前一步的距离为负,当前一步的距离为正,则发生了太阳正午
  2. 如果前一步的距离为正,当前一步的距离为负,则发生了午夜

同样,如果发生上述情况之一,我们可以通过线性插值计算事件的精确时间

double corrTime = time - distance / (distance - oldDistance);

其中`time`是当前时间,`distance`是当前距离,`oldDistance`是前一步的距离。

应用程序

如果你启动应用程序并按下“开始”按钮,地球将在12月初绕太阳运行。如果你等待大约一分钟,它将处于1月份的位置,右侧的表格将显示某天的日出、正午和日落时间以及它们以秒为单位的差异

再次按下“开始”按钮会停止模拟。您可以使用此按钮左侧的控件选择开始日期和月份。“中午”按钮让模拟在指定时间开始,但会在下一个中午停止。

您可以随时使用“演示”按钮右侧的组合框更改相机位置。其中一些位置被称为“固定”,这意味着您无法交互式地修改位置。“自由”位置允许您使用鼠标控制相机的位置和方向。以下位置可用

固定:概览 1

摄像机位于三维空间中的某个点(0.5,-1,12),并指向原点,向上向量具有正z值。在此视图中,太阳静止不动,地球逆时针绕太阳移动。

固定:地球黄极

摄像机位于地球正上方,距离全局 z 方向(即黄道极方向)10个单位。它指向 z 方向下方,向上向量在 y 方向。现在地球静止不动但自转,太阳绕地球移动。

固定:地球北极

现在摄像机位于北极正上方,距离为10,指向极轴下方,向上向量为全局y方向。像以前一样,地球静止不动但自转,太阳绕地球移动。

固定:地球位置

这是一个有趣的视角,从观察者正上方俯视地球。想象一下摄像机安装在观察者位置的一座巨大的摩天大楼上,指向观察者,向上向量指向北极。在此视图中,地球完全静止,甚至不自转,因为摄像机以相同的方式旋转。但现在太阳似乎每天绕地球移动一次!

固定:地球对跖点

这同样是一个非常有趣的视角,从所谓的反地球的位置看。反地球是一个假设的行星,它总是位于太阳的另一侧,与地球相对。我记得有一部名为《太阳远征之旅》的电影,就采用了这个假设。嗯,那是很久以前的事了!

在此视图中,地球和太阳都静止不动(地球自转),但现在我们可以看到地球围绕太阳运行时其极轴显着的视自转。当然,地球轴相对于全球坐标系固定是其基本特征,但从这个位置观察地球可以揭示很多正在发生的事情。

自由:从位置

这是我们都最熟悉的视图。摄像机位于观察者位置并指向南方。现在我们可以看到太阳在天空中移动,就像我们在现实生活中看到的那样。摄像机不是固定的,因此您可以通过拖动鼠标左键进行旋转。您还可以使用鼠标滚轮放大和缩小。

自由:概览 2 和 3

与概览1一样,摄像机位于空间中的固定位置。但这次,您可以通过拖动鼠标左键更改方向,并通过Ctrl + 方向键(和Ctrl PgUp PgDn)更改位置。

更多控件

在控制区域的中央,你会找到控制偏心率、倾斜度、观察者纬度和模拟速度的控件。值为10会将时间步长设置为1/100秒。此步长可以通过旋转控件增加/减少2倍。你甚至可以通过按下“反向”按钮来反转时间

下一组控件用于添加或删除额外的3D模型,这些模型可能有助于理解正在发生的事情:全局坐标系、黄道、观察者位置、地平线、子午线和阴影边界

构建3D场景

3D场景是用我的小型`WFTools3D`库创建的,你可以在CodeprojectGithub上找到它。根据所选设置,它包含或多或少的3D模型,但它总是会显示太阳和地球。

太阳和地球都是`WFTools3D.Sphere`类型。太阳的半径为0.2,始终位于原点,而地球的半径为1,其位置和旋转状态在调用渲染计时器时更新

void Update()
{
    earth.LockUpdates(true);
    earth.Position = simulator.EarthPosition;
    earth.Rotation1 = simulator.EarthRotation;
    earth.Rotation2 = simulator.AxialTilt;
    earth.LockUpdates(false);
    ...
}

在应用与`Position`对应的平移之前,`Rotation1`和`Rotation2`都应用于模型的变换矩阵。还有一个属性`Rotation3`,它在平移之后应用,但这里没有使用。

`LockUpdates(true)`方法可防止在设置单个3D属性时重新计算变换矩阵。设置所有属性后,`LockUpdates(false)`将更新矩阵。

许多额外的3D模型,例如观测者位置、极轴、地平线或阴影边界,都是地球模型的子模型。因此,它们不需要在计时器方法中更新。它们将跟随地球自转并绕太阳公转!

演示模式

演示模式是一种课程,旨在通过文本和模拟器来解释时间方程。它从地球季节的简单解释开始,以轴倾斜对太阳日长度更复杂的影响结束。

模拟参数,即开始时间、观测者纬度、倾斜度和偏心率,都会自动调整以突出某些情况。一旦你浏览完27页,你对这种现象的理解至少应该有所提高。至少我是这么希望的!

查找真实的日出和日落时间

如果您想查找您家乡的真实日出和日落时间,请访问calsky.com。您可以输入您的位置、开始日期和持续时间,您将获得日出、日落和中天时间(即太阳正午时间)。

结束

我知道又是一段漫长的旅程,但我希望您喜欢它!编程愉快!

历史

  • 2017年2月2日:首次上传
  • 2017年3月20日:更新了第一张图片和两个下载文件
© . All rights reserved.