logo  How To Calculate Moon Phase Dates
This Chapter
Sun and Moon
Equinox&Solstice
Moon Phases
Sun Rise&Set
Chapters
Home Page
Colours, RGB
Computer Specifications
Dates&Times
Disk Drives
Files
Folders
GPS and OS Ref
VB.Net Forms
Image Files
If & Select
List/Array
Mathematics
NuGet
Sound
String Functions
Sun and Moon
User Controls
Validation
DigitalDan Sites
My Other Sites
Contact Site

Note
Some pages
may contain
inaccuracies
Hits=5
This formula calculates dates for New Moons, First Quarter Moons, Full Moons and Third Quarter Moons. It is based on the Calendrical Calculation books by Meeus. However, as with any Calendrical Calculation, programmers need to be aware of certain limitations.

Public Shared Function MoonPhases(yyyy As Integer, UseLocalTime As Boolean) As List(Of PhaseDate)
 ' collect all moon phases for year and return result as List(of PhaseDate)
 ' The Structure for PhaseDate and Enum for PhaseName are defined within this code
 ' Moon phase calculations based on "Calendrical Calculations (Meeus)" in PhasesOfTheMoon function

 ' yyyy = required year
 ' If UseLocalTime = False Then all times wil be Universal Time (also known as UT, GMT, Greenwich Mean Time or Time-Zone 0)
 ' If UseLocalTime = True Then all times will be in host computers local time (adjusted for PC time zone, summer-time etc.)

 ' Estimate k at start of year
 Dim estimate_k As Double = (yyyy - 1900) * 12.37 ' 12.37 is approx average lunar cycles per year
 Dim k As Integer = CInt(Math.Floor(estimate_k - 1))
 ' the -2 is because we do not want to miss first cycle of year. we guessed k and must allow small margin of error
 Dim pd As PhaseDate : pd.phase = PhaseName.NewMoon : pd.dat = New Date(yyyy, 1, 1, 0, 0, 0, 0, 0)
 ' dummy value - set to ensure While starts first loop and no issues with undefined variable
 Dim ret As New List(Of PhaseDate)
 While pd.dat.Year <= yyyy
  pd = PhasesOfTheMoon(k + 0, UseLocalTime)
  If pd.dat.Year = yyyy Then ret.Add(pd)
  pd = PhasesOfTheMoon(k + 0.25, UseLocalTime)
  If pd.dat.Year = yyyy Then ret.Add(pd)
  pd = PhasesOfTheMoon(k + 0.5, UseLocalTime)
  If pd.dat.Year = yyyy Then ret.Add(pd)
  pd = PhasesOfTheMoon(k + 0.75, UseLocalTime)
  If pd.dat.Year = yyyy Then ret.Add(pd)
  k += 1
 End While
 Return ret
End Function

Private Shared Function PhasesOfTheMoon(k As Double, UseLocalTime As Boolean) As PhaseDate
 ' This function based on Calendrical Calculations (Meeus) Chapter 32
 ' it finds the moon phase dates of a lunar cycle
 ' valid from 1 Jan 1900

 ' k = lunar cycle number (always integer) + required moon phase (double)
 ' required moon phase always 0, 0.25, 0.5 or 0.75
 ' where 0=New .25=Q1 .5=Full .75=Q3

 ' If UseLocalTime = False Then date/time will be Universal Time (also known as UT, GMT, Greenwich Mean Time or Time-Zone 0)
 ' If UseLocalTime = True Then date/time will be in host computers local time (adjusted for PC time zone, summer-time etc.)

 ' Times accurate to within a few minutes but moany commercial tables only quote the day

 Dim corr, F, JD, M, Mo, T, temp As Double
 Dim moonType As PhaseName
 Dim ret As PhaseDate
 Dim JDE_Greg As Date
 ' Make certain k is exact multiple 0.25
 k = Math.Round(k * 4) / 4
 ' determine moon type from k
 temp = k - Math.Floor(k)
 Select Case temp ' allow a little margin to avoid trivial rounding error problems
  Case 0.125 To 0.374 : moonType = PhaseName.FirstQuarterMoon
  Case 0.375 To 0.625 : moonType = PhaseName.FullMoon
  Case 0.625 To 0.874 : moonType = PhaseName.ThirdQuarterMoon
  Case Else : moonType = PhaseName.NewMoon
 End Select
 T = k / 1236.85
 JD = 2415020.75933 + 29.53058868 * k + 0.0001178 * T * T - 0.000000155 * T * T * T
 JD += 0.00033 * SinDeg((166.56 + 132.87 * T - 0.009173 * T * T) Mod 360)
 M = (359.2242 + 29.10535608 * k - 0.0000333 * T * T - 0.00000347 * T * T * T) Mod 360
 Mo = (306.0253 + 385.81691806 * k + 0.0107306 * T * T - 0.00001236 * T * T * T) Mod 360
 F = (21.2964 + 390.67050646 * k - 0.0016528 * T * T - 0.00000239 * T * T * T) Mod 360
 Select Case moonType
  Case PhaseName.NewMoon, PhaseName.FullMoon
   corr += (0.1734 - 0.000393 * T) * SinDeg(M)
   corr += 0.0021 * SinDeg(2 * M)
   corr -= 0.4068 * SinDeg(Mo)
   corr += 0.0161 * SinDeg(2 * Mo)
   corr -= 0.0004 * SinDeg(3 * Mo)
   corr += 0.0104 * SinDeg(2 * F)
   corr -= 0.0051 * SinDeg(M + Mo)
   corr -= 0.0074 * SinDeg(M - Mo)
   corr += 0.0004 * SinDeg(2 * F + M)
   corr -= 0.0004 * SinDeg(2 * F - M)
   corr -= 0.0006 * SinDeg(2 * F + Mo)
   corr += 0.001 * SinDeg(2 * F - Mo)
   corr += 0.0005 * SinDeg(M + 2 * Mo)
  Case PhaseName.FirstQuarterMoon, PhaseName.ThirdQuarterMoon
   corr += (0.1721 - 0.0004 * T) * SinDeg(M)
   corr += 0.0021 * SinDeg(2 * M)
   corr -= 0.628 * SinDeg(Mo)
   corr += 0.0089 * SinDeg(2 * Mo)
   corr -= 0.0004 * SinDeg(3 * Mo)
   corr += 0.0079 * SinDeg(2 * F)
   corr -= 0.0119 * SinDeg(M + Mo)
   corr -= 0.0047 * SinDeg(M - Mo)
   corr += 0.0003 * SinDeg(2 * F + M)
   corr -= 0.0004 * SinDeg(2 * F - M)
   corr -= 0.0006 * SinDeg(2 * F + Mo)
   corr += 0.0021 * SinDeg(2 * F - Mo)
   corr += 0.0003 * SinDeg(M + 2 * Mo)
   corr += 0.0004 * SinDeg(M - 2 * Mo)
   corr -= 0.0003 * SinDeg(2 * M + Mo)
 End Select
 If moonType = PhaseName.FirstQuarterMoon Then
  corr += 0.0028 - 0.0004 * CosDeg(M) + 0.0003 * CosDeg(Mo)
 End If
 If moonType = PhaseName.ThirdQuarterMoon Then
  corr += -0.0028 + 0.0004 * CosDeg(M) - 0.0003 * CosDeg(Mo)
 End If
 ret.phase = moonType
 JDE_Greg = New Date(1858, 11, 17, 0, 0, 0, 0, 0)
 ret.dat = JDE_Greg.AddDays(JD + corr - 2400000.5)
 If UseLocalTime Then ret.dat = ret.dat.ToLocalTime
 Return ret
End Function

Private Shared Function SinDeg(a As Double) As Double
 Return Math.Sin(a * Math.PI / 180)
End Function

Private Shared Function CosDeg(a As Double) As Double
 Return Math.Cos(a * Math.PI / 180)
End Function

Public Structure PhaseDate
 Dim phase As PhaseName
 Dim dat As Date
End Structure

Public Enum PhaseName
 NewMoon
 FirstQuarterMoon
 FullMoon
 ThirdQuarterMoon
End Enum
  
 
How to Call Function
Obtain list of every Moon Phase in the year 2026. Results should be in Universal Time

Dim ListPhaseDate As List(Of PhaseDate) = MoonPhases(2026, False)
  
Obtain list of every Moon Phase in the year 2027. Results should be in the local time zone of the host computer

Dim ListPhaseDate As List(Of PhaseDate) = MoonPhases(2027, True)
  

DigitalDan.co.uk