[HN Gopher] Show HN: Tiny Moon - Swift library to calculate the ...
       ___________________________________________________________________
        
       Show HN: Tiny Moon - Swift library to calculate the moon phase
        
       Tiny Moon is a tiny Swift library to calculate the moon phase for
       any given date, works super fast, and works completely offline.
       All of this started when I realized that we only have 12, sometimes
       13, full moon's in a year. That doesn't seem like that many.  I set
       out to build a MacOS app to remind me when a full moon occurs, so
       that I could take a moment and step outside to appreciate it.  The
       MacOS app I ended up creating can be found at
       https://apps.apple.com/us/app/tiny-moon/id6502374344 along with the
       source code [0], all powered by the Tiny Moon library.  I knew that
       I wanted the app to work offline, so working with a network request
       was out of the picture. Taking inspiration from SunCalc [1] and
       Moontool for Windows [2], I decided to create my own library and
       wrote Tiny Moon as a Swift Package to power my app.  The app tries
       to be as minimal as possible, does what it does very fast, and
       works completely offline.  [0]
       https://github.com/mannylopez/TinyMoonApp  [1]
       https://github.com/mourner/suncalc  [2]
       https://www.fourmilab.ch/moontoolw/
        
       Author : mannylopez
       Score  : 67 points
       Date   : 2024-07-25 15:17 UTC (7 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | jes5199 wrote:
       | nice! I have needed this before. I think you're using the Meeus
       | algorithm from Astronomical Algorithms? it's a classic, great
       | choice
        
         | mannylopez wrote:
         | Yes, pretty much every good library I came across referenced
         | Meeus' Astronomical Algorithms [0] book and formulas. Those
         | were a bit dense for me to fully parse, but Dr. Louis Strous`
         | page [1] on finding the position of the moon helped simplify it
         | for me (although that implementation is less accurate, I
         | think).
         | 
         | The algorithm in Moontool for Windows [2], which Tiny Moon is
         | based off of, is based off of Meeus' algorithm.
         | 
         | 0.
         | https://www.agopax.it/Libri_astronomia/pdf/Astronomical%20Al...
         | 
         | 1. https://aa.quae.nl/en/reken/hemelpositie.html#4
         | 
         | 2. https://www.fourmilab.ch/moontoolw/
        
       | ks2048 wrote:
       | Nice work. Just FYI for anybody else - it adds an icon to status
       | bar (if that's what it's called? - top right icons). I thought it
       | was going to open an app window and didn't notice the icon, so
       | thought it wasn't working. (In hindsight, it's clear from
       | screenshots in app store).
        
         | asrael_io wrote:
         | I think it's called the menu bar, and apps that don't open
         | windows (with an icon in the menu bar) are known as "menu bar
         | apps". Until recently, these were a PITA to implement with
         | Apple's SDK. Thankfully they provided API support sometime I
         | think starting with macOS 13... before that it was pretty
         | kludgy.
        
           | rgovostes wrote:
           | The menus themselves are called "menu bar extras":
           | https://developer.apple.com/design/human-interface-
           | guideline...
        
       | shainvs wrote:
       | Is there a plan to add this for linux / windows? Either way,
       | super cool project
        
         | mannylopez wrote:
         | Good news! According to Swift Package Index [0], Tiny Moon is
         | already compatible with Linux environments.
         | 
         | 0. https://swiftpackageindex.com/mannylopez/TinyMoon/
        
         | robsh wrote:
         | The following formula will return the closest moon phase emoji
         | in Excel:
         | 
         | =LET(phase,MOD(ROUND(MOD(NOW(),29.5275)/3.691,0)-2,8)+1,UNICHAR
         | (127760+phase)))
        
       | 082349872349872 wrote:
       | Here's a tiny calculator for moon phase that I kludged up ca.
       | 2018 but (at least as of this month) is still tracking the full
       | moon (which makes sense given that the algo came out of a dead
       | tree source from over half a century ago?):                 _=min
       | lphase = lambda y,m,d: _( lkp(ph,p)             for lkp in
       | [lambda t,x: _(v for (kl,v),(kh,w)                             in
       | zip(t,t[1:]) if kl <= x < kh)]             for daynum  in [lambda
       | y,m,d: daynum(y-1,m+12,d) if m<3 else
       | y*365 + y//4 - y//100 + y//400 + (153*m+3)//5 + d]
       | for o   in [daynum(y,m,d)-daynum(2000,1,6)]             for p
       | in [o%29.53] # mean; varies significantly!             for ph  in
       | [[(0,"new"),(0.5,"waxing crescent"),(7,"first quarter"),
       | (8,"waxing gibbous"),(14.5,"full"),(15.5,"waning gibbous"),
       | (21.7,"last quarter"),(22.7,"waning crescent"),(29,"new"),
       | (30,None)]] )
        
         | madcaptenor wrote:
         | So this is just saying that the phase of the moon is the day
         | mod 29.53, starting from a new moon on 2000-01-06. That's about
         | a minute off the actual mean length of a lunation - I guess the
         | error from that approximation is less than the approximation in
         | your "varies significantly"?
         | 
         | (For what it's worth - 29.53 * 300 = 8859 exactly, and
         | 2000-01-06 + 8859 days = 2024-04-08, and I am quite sure there
         | was a new moon on the latter date because of the solar
         | eclipse.)
        
           | 082349872349872 wrote:
           | Yes. (any cultures that have a purely lunar calendar could do
           | away with all the date fiddling? but then again, I guess
           | they'd just _know_ when the next full moon would be...)
           | 
           | [If that constant is only a minute off, it ought to be good
           | for a few centuries more, and I'm not planning on being
           | around longer than decades, so probably good enough for my
           | purposes.]
        
             | gmiller123456 wrote:
             | I think the point is that the lunations vary by a couple of
             | days within a year, so you might confuse users by stating a
             | phase is on the wrong day when they are unaware a low
             | accuracy algorithm is being used. But that algorithm
             | probably would be good enough for just drawing an icon,
             | since the differences would be imperceptable.
             | 
             | Honestly, I recommend people use the most accurate
             | algorithm they practically can, even if it's overkill for
             | the given application. This just avoids user confusion when
             | different apps give different answers, even if it's not
             | significant.
             | 
             | E.g., I have ported VSOP87 which gives the position of the
             | moon and planets to sub-arcsecond accuracy to a couple of
             | dozen languages. They are much, much longer than the
             | "snippets", but are not impractical, and users won't notice
             | much difference in application size or computation time.
             | https://github.com/gmiller123456/vsop87-multilang
        
       | gmiller123456 wrote:
       | I have a site with a lot of these stand alone "snippets" so that
       | you don't have to include/port an entire astronomy library just
       | to get the Sun rise/set times, etc.
       | https://www.celestialprogramming.com/
       | 
       | Most of them are written in JavaScript only, but specifically
       | written to be easy to port to other languages.
        
       | kickingvegas wrote:
       | Side note, if you use Emacs you can get the phases of the Moon by
       | pressing "M" in either calendar or Org Agenda.
        
         | eesmith wrote:
         | With M-x lunar-phases you get the next three lunar months;
         | something like:                 Thursday, June 6, 2024: New
         | Moon 8:40am (EDT)       Friday, June 14, 2024: First Quarter
         | Moon 1:20am (EDT)          .. I removed a few lines ...
         | Monday, August 19, 2024: Full Moon 2:24pm (EDT)       Monday,
         | August 26, 2024: Last Quarter Moon 5:34am (EDT
         | 
         | Also, M-x sunrise-sunset computes sunrise and sunset after you
         | give it lat/long.
        
       | ChrisMarshallNY wrote:
       | I don't really have use for this, but I must compliment the
       | author on a job well-done. The code is well-structured, well-
       | documented, well-tested, and well-designed.
        
         | mannylopez wrote:
         | Thank you! I was a technical writer before learning how to
         | program, so it's important for me to write well-documented and
         | well-tested code.
         | 
         | Doing so also allowed me to completely remove and replace my
         | first attempt at implementing the moon phase algorithm when it
         | turned out to be not-accurate enough (the values were off by
         | about 4 hours).
        
       | rubiquity wrote:
       | I know a lot of people into fishing that would love this as an
       | app to quickly check the moon phase on a given date when planning
       | a multi-day fishing trip or deciding when to go out. Apex
       | predators are typically less hungry around and during a full moon
       | due to the extra light making hunting at night easy.
        
       | whartung wrote:
       | And then, there was an anecdote!
       | 
       | I bought my friends daughter a watch for her birthday. She was,
       | like, 12 or something. I got it at Target.
       | 
       | And it had a moon phase dial! How about that?!
       | 
       | So I was determined to set it accurately for her.
       | 
       | To wit I started dredging through the internet. And to be
       | completely honest, I'm not quite sure how I was doing that,
       | having nothing but a Netcom.com shell account available to me.
       | Perhaps I was using Lynx, or using some mail gateway, or who
       | knows what. It wasn't no 10 seconds on Google, I'll tell you
       | that.
       | 
       | In the end, I stumbled upon some code for my HP-48. Aha! This
       | should do nicely!
       | 
       | Somehow, I got the code into the calculator. Did I type it in?
       | Did I download it over Kermit? Who knows. Times were moving fast
       | back then. Somehow, someway, however, I got that code in and
       | calculated away.
       | 
       | Finally! ACCURATE results. Done with precision and math and
       | engineering. Done Right!
       | 
       | To wit, I then proceeded to get the watch set properly.
       | 
       | And...it was a fashion watch for a 12 year old girl from Target.
       | This may come as a shock to some, I was obviously taken aback by
       | it, however -- the moon phase did not work. It was just a moon on
       | a dial that moved, though some undetermined mechanism. It could
       | not be set independently.
       | 
       | Oh.
        
       ___________________________________________________________________
       (page generated 2024-07-25 23:04 UTC)