Swift Package Manager

Tiny Moon icon

Tiny Moon Swift 软件包

一个小巧的 Swift 库,用于计算任何给定日期的月相,速度超快,并且完全离线工作。

兼容 iOS 和 MacOS。

快速开始

// Get the moon phase for right now
let moon = TinyMoon.calculateMoonPhase()

安装

  1. 打开你现有的 Xcode 项目或创建一个新的。
  2. 打开 Swift Packages Manager。
    • 在项目导航器中,选择你的项目文件以打开项目设置。
    • 导航到 Package Dependencies 选项卡。
  3. 添加 Tiny Moon 软件包。
    • 点击选项卡底部的 + 按钮。
    • 在出现的对话框中,输入 Tiny Moon 的 URL:https://github.com/mannylopez/TinyMoon.git
  4. 指定版本规则。
    • Xcode 将提示你为软件包指定版本规则。“Up to Next Major Version”(直到下一个主版本)确保与未来不引入重大更改的更新兼容。
    • 点击 Add Package(添加软件包)。

Xcode package dialog box

用法

现在 Tiny Moon 已添加到你的项目中,导入它并简单地传入你想知道月相的 DateTimeZone。 如果没有传入日期,则将使用你系统的当前 Date

一个使用 Tiny Moon 的示例应用

import SwiftUI
import TinyMoon

struct SimpleMoonView: View {

  private let moon = TinyMoon.calculateMoonPhase()

  var body: some View {
    VStack(spacing: 16) {
      Text(moon.date.toString())
      Text(moon.emoji)
      Text(moon.name)
      Text("Illumination: \(moon.illuminatedFraction)")
      Text("\(moon.ageOfMoon.days) days, \(moon.ageOfMoon.hours) hours, \(moon.ageOfMoon.minutes) minutes")
      Text("Full Moon in \(moon.daysTillFullMoon) days")
      Text("New Moon in \(moon.daysTillNewMoon) days")
    }
  }
}

#Preview {
  SimpleMoonView()
}

Simple Moon View

API

入口点

库的主要入口点是 TinyMoon 命名空间。

从那里,你可以访问函数 calculateMoonPhasecalculateExactMoonPhase

public enum TinyMoon {
  public static func calculateMoonPhase(
    _ date: Date = Date(),
    timeZone: TimeZone = TimeZone.current)
    -> Moon
  {
    Moon(date: date, timeZone: timeZone)
  }

  public static func calculateExactMoonPhase(_ date: Date = Date()) -> ExactMoon {
    ExactMoon(date: date)
  }
}

MoonExactMoon

如果主要月相(新月、上弦月、满月、下弦月)恰好在特定的一天内发生,则 Moon 对象会优先考虑这些主要月相。

ExactMoon 对象始终返回传入的特定日期和时间的精确值。

例如,假设满月发生在 2024 年 8 月 19 日 13:25 UTC

import Foundation

// The Date we will query for is August 19, 2024 at 02:00 UTC
let isoFormatter = ISO8601DateFormatter()
isoFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let date = isoFormatter.date(from: "2024-08-19T02:00:00Z")!

let moon = TinyMoon.calculateMoonPhase(date, timeZone: isoFormatter.timeZone) // If you don't specify a TimeZone, it will default to the system's TimeZone
print(moon.name)	// Full Moon
print(moon.emoji)	// 🌕

let exactMoon = TinyMoon.calculateExactMoonPhase(date)
print(exactMoon.name)	// Waxing Gibbous
print(exactMoon.emoji)	// 🌔

ExactMoon 将返回 .waxingGibbous(盈凸月),因为这更准确地表示了 02:00 UTC 时间的月相。Moon 将返回 .fullMoon(满月),因为满月发生在当天。

Moon 属性

属性 类型 描述
moonPhase (月相) MoonPhase (月相) 包含所有 8 种月相的枚举
name (名称) 字符串 MoonPhase 枚举案例的字符串表示
emoji (表情符号) 字符串 月相的表情符号
date (日期) 日期 传入 Moon 对象的日期
julianDay (儒略日) 双精度浮点数 自儒略历元开始以来连续的天数计数。 用于天文计算 (维基百科)
daysTillFullMoon (距满月天数) 整数 如果当前 date 是满月,则返回 0
daysTillNewMoon (距新月天数) 整数 如果当前 date 是新月,则返回 0
daysElapsedInCycle (周期中经过的天数) 双精度浮点数 合朔周期中经过的天数,以分数表示
ageOfMoon (月龄) (天: 整数, 小时: 整数, 分钟: 整数) 月亮的年龄,以天、小时、分钟为单位
illuminatedFraction (照明部分) 双精度浮点数 月亮的照明部分,其中 0.0 = 新月,1.00 = 满月
phaseFraction (月相分数) 双精度浮点数 月相,以分数表示。 见下表。
distanceFromCenterOfEarth (距地心距离) 双精度浮点数 月亮距地心的距离,单位为千米
fullMoonName (满月名称) 字符串? 返回通俗的满月名称

phaseFraction 的值和对应的表情符号

phaseFraction (月相分数) 名称 表情符号
0.0 新月 🌑
娥眉月 🌒
0.25 上弦月 🌓
盈凸月 🌔
0.5 满月 🌕
亏凸月 🌖
0.75 下弦月 🌗
残月 🌘

演示

以下是使用 Tiny Moon Swift 软件包构建的

MacOS

一个 MacOS 应用程序(在 App Store 中可用),可在你的工具栏中将当前月相显示为表情符号。

源代码: https://github.com/mannylopez/TinyMoonApp

Toolbar Detail view

iOS

一个简单的 iOS 应用程序,用于展示如何使用 Tiny Moon Swift 软件包

源代码: https://github.com/mannylopez/TinyMoonMobile

Mobile app

致谢

非常感谢 suncalc,一个用于计算给定时间的月球位置和月相(以及太阳位置和日光阶段)的小型 JavaScript 库。 它帮助我理解了计算月相所需的底层公式。

我通过 suncalc 找到的很棒的资源包括但不限于:

非常非常感谢 John Walker,他编写了 Moontool for Windows 并将 C 源代码发布到公共领域。 这就是计算月相的主要公式的来源,我发现它非常准确。