home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 5_2007-2008.ISO / data / Zips / Lunar_Calc20377012142006.psc / MoonPhase.bas < prev   
BASIC Source File  |  2006-11-03  |  17KB  |  528 lines

  1. Attribute VB_Name = "MoonPhase"
  2. Option Explicit
  3. Private Declare Function GetTimeZoneInformation Lib "kernel32" (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long
  4.  
  5. Private Const TIME_ZONE_ID_INVALID = -1
  6. Private Const TIME_ZONE_ID_UNKNOWN = 0
  7. Private Const TIME_ZONE_ID_STANDARD = 1
  8. Private Const TIME_ZONE_ID_DAYLIGHT = 2
  9.  
  10. Public Type SYSTEMTIME
  11.     wYear As Integer
  12.     wMonth As Integer
  13.     wDayOfWeek As Integer
  14.     wDay As Integer
  15.     wHour As Integer
  16.     wMinute As Integer
  17.     wSecond As Integer
  18.     wMilliseconds As Integer
  19. End Type
  20.  
  21. Public Type TIME_ZONE_INFORMATION
  22.     Bias As Long
  23.     StandardName As String * 64
  24.     StandardDate As SYSTEMTIME
  25.     StandardBias As Long
  26.     DaylightName As String * 64
  27.     DaylightDate As SYSTEMTIME
  28.     DaylightBias As Long
  29. End Type
  30.  
  31. Private Const A_SECOND = 0.00001158 ' one second as a fraction of a day
  32. Private Const LPERIOD = 29.530589 ' average days between lunations
  33. Private Const EPOCH = 8388.51399305556 ' days from 01/01/1900 til 12/18/1922 12:20:09 UT, lunation 0
  34. Private Const PI = 3.14159265359
  35.  
  36. Private JDE As Double ' Julian Day Ephemeris of phase event
  37. Private E As Double ' Eccentricity anomaly
  38. Private M As Double ' Sun's mean anomaly
  39. Private M1 As Double ' Moon's mean anomaly
  40. Private F As Double ' Moon's argument of latitude
  41. Private O As Double ' Moon's longitude of ascending node
  42. Private A(15) As Double ' Planetary arguments
  43. Private W As Double ' Added correction for quarter phases
  44.  
  45. Public Stopping As Boolean
  46. Public TheDate As Date
  47. Public Sub DrawMoonPhase(PhaseAngle As Single, MoonBox As PictureBox)
  48.     Dim cx As Single
  49.     Dim cy As Single
  50.     Dim Lat As Single
  51.     Dim R As Single
  52.     Dim X1 As Single
  53.     Dim Y1 As Single
  54.     Dim X2 As Single
  55.     Dim Y2 As Single
  56.     Dim Sign As Integer
  57.     Dim K As Double
  58.     K = Atn(1) / 45
  59.     MoonBox.ScaleMode = 3
  60.     MoonBox.DrawWidth = 2
  61.     R = MoonBox.ScaleWidth / 2
  62.     cx = R
  63.     cy = R
  64.     If PhaseAngle >= 360 Then
  65.         PhaseAngle = PhaseAngle Mod 360
  66.     End If
  67.     If PhaseAngle > 180 Then
  68.         Sign = 1
  69.         PhaseAngle = PhaseAngle - 180
  70.     Else
  71.         Sign = -1
  72.     End If
  73.     If PhaseAngle = 180 Then Exit Sub
  74.     MoonBox.Cls
  75.     For Lat = -90 To 90
  76.         X1 = cx + R * Cos(PhaseAngle * K) * Cos(Lat * K)
  77.         Y1 = cy - R * Sin(Lat * K)
  78.         X2 = cx + R * Cos(Lat * K) * Sign
  79.         Y2 = cy - R * Sin(Lat * K)
  80.         MoonBox.Line (X1, Y1)-(X2, Y2), RGB(12, 12, 12)
  81.     Next
  82. End Sub
  83. Public Sub CyclePhases(MoonBox As PictureBox)
  84.     Dim PhaseAngle As Integer
  85.     Do While Not Stopping
  86.         If PhaseAngle = 361 Then PhaseAngle = 0
  87.         DoEvents
  88.         DrawMoonPhase CSng(PhaseAngle), MoonBox
  89.         PhaseAngle = PhaseAngle + 1
  90.     Loop
  91. End Sub
  92. Public Function MonthName(ByVal Month As Integer) As String
  93.     Select Case Month
  94.     Case 1
  95.         MonthName = "January"
  96.     Case 2
  97.         MonthName = "February"
  98.     Case 3
  99.         MonthName = "March"
  100.     Case 4
  101.         MonthName = "April"
  102.     Case 5
  103.         MonthName = "May"
  104.     Case 6
  105.         MonthName = "June"
  106.     Case 7
  107.         MonthName = "July"
  108.     Case 8
  109.         MonthName = "August"
  110.     Case 9
  111.         MonthName = "September"
  112.     Case 10
  113.         MonthName = "October"
  114.     Case 11
  115.         MonthName = "November"
  116.     Case 12
  117.         MonthName = "December"
  118.     End Select
  119. End Function
  120. Public Function MonthNumber(Name As String) As Integer
  121.     Select Case Name
  122.     Case "January"
  123.         MonthNumber = 1
  124.     Case "February"
  125.         MonthNumber = 2
  126.     Case "March"
  127.         MonthNumber = 3
  128.     Case "April"
  129.         MonthNumber = 4
  130.     Case "May"
  131.         MonthNumber = 5
  132.     Case "June"
  133.         MonthNumber = 6
  134.     Case "July"
  135.         MonthNumber = 7
  136.     Case "August"
  137.         MonthNumber = 8
  138.     Case "September"
  139.         MonthNumber = 9
  140.     Case "October"
  141.         MonthNumber = 10
  142.     Case "November"
  143.         MonthNumber = 11
  144.     Case "December"
  145.         MonthNumber = 12
  146.     End Select
  147. End Function
  148. Public Function TimeZone() As String
  149.     Dim TZ As TIME_ZONE_INFORMATION
  150.     Dim Bias As Double
  151.     Dim Temp As Date
  152.     Const HOUR = 0.04167
  153.     GetTimeZoneInformation TZ
  154.     Bias = TZ.Bias / 60
  155.     Temp = CDate(HOUR * Bias)
  156.     If Bias = 0 Then
  157.         TimeZone = "(GMT)"
  158.     ElseIf Sgn(Bias) = 1 Then
  159.         TimeZone = "(GMT -" & Format(Temp, "hh:mm") & ")"
  160.     Else
  161.         TimeZone = "(GMT +" & Format(Temp, "hh:mm") & ")"
  162.     End If
  163. End Function
  164. Public Function WeekdayName2(Weekday As Integer) As String
  165.     Select Case Weekday
  166.     Case 1
  167.         WeekdayName2 = "Sunday"
  168.     Case 2
  169.         WeekdayName2 = "Monday"
  170.     Case 3
  171.         WeekdayName2 = "Tuesday"
  172.     Case 4
  173.         WeekdayName2 = "Wednesday"
  174.     Case 5
  175.         WeekdayName2 = "Thursday"
  176.     Case 6
  177.         WeekdayName2 = "Friday"
  178.     Case 7
  179.         WeekdayName2 = "Saturday"
  180.     End Select
  181. End Function
  182. Public Sub WriteAllPhases()
  183.     Dim i As Long
  184.     Dim FileNumber As Integer
  185.     FileNumber = FreeFile
  186.     Open App.Path & "\Phases.txt" For Output As #FileNumber
  187.     For i = -22546 To 99898
  188.         Print #FileNumber, Format(Str(i), "#00000") & " " & _
  189.                 Format(JulianDaysToUT(MoonPhaseByLunation(i, 0)), "mm/dd/yyyy hh:mm:ss") & "  " & _
  190.                 Format(JulianDaysToUT(MoonPhaseByLunation(i, 1)), "mm/dd/yyyy hh:mm:ss") & "  " & _
  191.                 Format(JulianDaysToUT(MoonPhaseByLunation(i, 2)), "mm/dd/yyyy hh:mm:ss") & "  " & _
  192.                 Format(JulianDaysToUT(MoonPhaseByLunation(i, 3)), "mm/dd/yyyy hh:mm:ss")
  193.     Next
  194.     Close
  195. End Sub
  196. Public Function Angle(AnyDate As Date) As Single
  197.     ' AnyDate must already be in UT
  198.     ' 0 = New, 180 = Full, 360 = New
  199.     Angle = Age(AnyDate) * 360 / 29.530589
  200. End Function
  201. Public Function ConvertToUT(Time As Date) As Date
  202.     ' convert system time to universal time and adjust for DST
  203.     Dim TZ As TIME_ZONE_INFORMATION
  204.     Dim Temp As Date
  205.     Dim Rtn As Long
  206.     Rtn = GetTimeZoneInformation(TZ)
  207.     If Rtn > TIME_ZONE_ID_UNKNOWN Then
  208.         
  209.         If Rtn = TIME_ZONE_ID_STANDARD Then
  210.             Temp = DateAdd("n", TZ.Bias, Time)
  211.         Else
  212.             Temp = DateAdd("n", (TZ.Bias + TZ.DaylightBias), Time)
  213.         End If
  214.         
  215.     End If
  216.     ConvertToUT = Temp
  217. End Function
  218. Public Function IsLeapYear(TheYear As Integer) As Boolean
  219.     Dim Remainder As Integer
  220.     Remainder = TheYear Mod 4
  221.     If Remainder = 0 Then
  222.         Remainder = TheYear Mod 100
  223.         If Remainder = 0 Then
  224.             Remainder = TheYear Mod 400
  225.             If Remainder = 0 Then
  226.                 IsLeapYear = True
  227.             Else
  228.                 IsLeapYear = False
  229.             End If
  230.         Else
  231.             IsLeapYear = True
  232.         End If
  233.     Else
  234.         IsLeapYear = False
  235.     End If
  236. End Function
  237. Public Function IsLeapYear2(Year As Integer) As Boolean
  238.     Dim x As Date
  239.     ' this is the shortcut method
  240.     On Error GoTo Err1
  241.     x = CDate("02/29/" & Year)
  242.     IsLeapYear2 = True
  243.     Exit Function
  244. Err1:
  245.     ' type mismatch date error
  246.     IsLeapYear2 = False
  247. End Function
  248. Public Function MoonDescription(AnyDate As Date) As String
  249.     Dim Phase(1 To 3) As Date
  250.     Dim i As Integer
  251.     ' since the actual phases are exact instants in time
  252.     ' the moon's description will always be in between two
  253.     If Not DateInLimits(AnyDate) Then Exit Function
  254.     For i = 1 To 3
  255.         'Phase(i) = UTtoLocal(JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate), i)))
  256.         Phase(i) = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate), i))
  257.     Next
  258.     If AnyDate >= Phase(3) Then
  259.         MoonDescription = "Waning Crescent"
  260.         ' then Last Quarter
  261.     ElseIf AnyDate >= Phase(2) Then
  262.         MoonDescription = "Waning Gibbous"
  263.         ' then Full Moon
  264.     ElseIf AnyDate >= Phase(1) Then
  265.         MoonDescription = "Waxing Gibbous"
  266.         ' then First Quarter
  267.     Else
  268.         MoonDescription = "Waxing Crescent"
  269.         ' then New Moon
  270.     End If
  271.     
  272.     
  273. End Function
  274. Public Function NextLastQuarter(AnyDate As Date) As Date
  275.     Dim Temp As Date
  276.     Temp = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate), 3))
  277.     If Temp > AnyDate Then
  278.     NextLastQuarter = Temp
  279. Else
  280. NextLastQuarter = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate) + 1, 3))
  281. End If
  282. End Function
  283. Public Function NextFirstQuarter(AnyDate As Date) As Date
  284.     Dim Temp As Date
  285.     Temp = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate), 1))
  286.     If Temp > AnyDate Then
  287.     NextFirstQuarter = Temp
  288. Else
  289. NextFirstQuarter = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate) + 1, 1))
  290. End If
  291. End Function
  292. Public Function PreviousNewMoon(AnyDate As Date) As Date
  293.     PreviousNewMoon = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate), 0))
  294. End Function
  295. Public Function NextNewMoon(AnyDate As Date) As Date
  296.     Dim Temp As Date
  297.     Temp = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate), 0))
  298.     If Temp > AnyDate Then
  299.     NextNewMoon = Temp
  300. Else
  301. NextNewMoon = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate) + 1, 0))
  302. End If
  303. End Function
  304. Public Function PreviousFirstQuarter(AnyDate As Date) As Date
  305.     Dim Temp As Date
  306.     Temp = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate), 1))
  307.     If Temp < AnyDate Then
  308.         PreviousFirstQuarter = Temp
  309.     Else
  310.         PreviousFirstQuarter = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate) - 1, 1))
  311.     End If
  312. End Function
  313. Public Function PreviousLastQuarter(AnyDate As Date) As Date
  314.     Dim Temp As Date
  315.     Temp = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate), 3))
  316.     If Temp < AnyDate Then
  317.         PreviousLastQuarter = Temp
  318.     Else
  319.         PreviousLastQuarter = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate) - 1, 3))
  320.     End If
  321. End Function
  322. Public Function PreviousFullMoon(AnyDate As Date) As Date
  323.     Dim Temp As Date
  324.     Temp = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate), 2))
  325.     If Temp < AnyDate Then
  326.         PreviousFullMoon = Temp
  327.     Else
  328.         PreviousFullMoon = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate) - 1, 2))
  329.     End If
  330. End Function
  331. Public Function NextFullMoon(AnyDate As Date) As Date
  332.     Dim Temp As Date
  333.     Temp = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate), 2))
  334.     If Temp > AnyDate Then
  335.     NextFullMoon = Temp
  336. Else
  337. NextFullMoon = JulianDaysToUT(MoonPhaseByLunation(Lunation(AnyDate) + 1, 2))
  338. End If
  339. End Function
  340. Public Function UTtoLocal(Time As Date) As Date
  341.     ' convert from universal time to system time and adjust for DST
  342.     Dim TZ As TIME_ZONE_INFORMATION
  343.     Dim Temp As Date
  344.     Dim Rtn As Long
  345.     Rtn = GetTimeZoneInformation(TZ)
  346.     If Rtn > TIME_ZONE_ID_UNKNOWN Then
  347.         If Rtn = TIME_ZONE_ID_STANDARD Then
  348.             Temp = DateAdd("n", -TZ.Bias, Time)
  349.         Else
  350.             Temp = DateAdd("n", -(TZ.Bias + TZ.DaylightBias), Time)
  351.         End If
  352.     End If
  353.     
  354.     UTtoLocal = Temp
  355. End Function
  356. Public Function DateInLimits(AnyDate As Date) As Boolean
  357.     On Error GoTo VbDateError
  358.     ' little tricky because 01/01/0100 23:59:59 is
  359.     ' numerically less than 01/01/0100 00:00:01 in VB
  360.     ' due to their being negative after converted to double
  361.     ' the +- integer part represents the day but the
  362.     ' absolute value of the decimal part is the
  363.     ' fraction of the day...see the Julian Day conversions
  364.     ' Also, in this program only, must use 01/17/0100 04:14:49
  365.     ' as a lower limit to avoid bad dates in intermediate functions
  366.     If CDbl(AnyDate) > -657418.176956019 And _
  367.             CDbl(AnyDate) <= 2958465.99999 And _
  368.             CDbl(AnyDate) <> -657418 Then
  369.     If CDbl(AnyDate) <= -115869 Or _
  370.             CDbl(AnyDate) > -115859.99999 Then
  371.     ' no such date as "10/5/1582" to "10/14/1582 23:59:59"
  372.     DateInLimits = True
  373. End If
  374. End If
  375. Exit Function
  376. VbDateError:
  377. DateInLimits = False
  378. ' type mismatch from bad Vb date
  379. End Function
  380. Public Function JulianDaysToUT(ByVal JD As Double) As Date
  381.     ' Convert Julian Days to Universal Time.
  382.     ' Julian Days are not the same as the Julian Calendar.
  383.     ' The Julian period began Jan 1st, 4713 B.C. 12:00:00 with year 1
  384.     ' The Julian period repeats after 7980 years (3268 A.D.)but for
  385.     ' conversion purposes we will pretend it continues
  386.     ' This will only work for dates >= 01/01/0100 00:00:01(VB limit)
  387.     Dim TheDay As Double
  388.     Dim Remainder As Double
  389.     If Not JulianWithinLimits(JD) Then Exit Function
  390.     ' correct for skip from 10/4/1582 to 10/15/1582
  391.     If JD >= 2299160.5 Then
  392.         TheDay = JD - 2415018.5
  393.     Else
  394.         TheDay = JD - 2415028.5
  395.     End If
  396.     ' handle positive and negative VB date values
  397.     If JD >= 2415020.5 Then ' positive VB dates > 1900
  398.         JulianDaysToUT = CDate(TheDay)
  399.     Else ' 100 A.D. to 1900
  400.         Remainder = CDbl(CDate(TheDay)) - Fix(CDate(TheDay))
  401.         If Remainder <> 0 Then
  402.             JulianDaysToUT = CDate(Fix(TheDay - 3) + (1 - Remainder))
  403.         Else
  404.             JulianDaysToUT = CDate(Fix(TheDay))
  405.         End If
  406.     End If
  407. End Function
  408. Public Function JulianWithinLimits(JD As Double) As Boolean
  409.     ' betwen the dates 01/01/0100 00:00:01 and
  410.     ' 12/31/9999 23:59:59  These are the limits of the
  411.     ' VB Date data type with one second added to the
  412.     ' beginning to avoid overflow during calculations
  413.     ' Cannot check for Oct 1582 error here
  414.     If JD >= 1757593.50001 And JD <= 5373484.49998843 Then
  415.         JulianWithinLimits = True
  416.     End If
  417. End Function
  418. Public Function UTtoJulianDays(ByVal AnyDate As Date) As Double
  419.     Dim TheDay As Double
  420.     Dim Remainder As Double
  421.     
  422.     If Sgn(CDbl(AnyDate)) = -1 Then
  423.         Remainder = CDbl(AnyDate) - Fix(CDbl(AnyDate))
  424.         If CDbl(AnyDate) - Remainder < CDbl(CDate("10/15/1582")) Then
  425.             TheDay = Fix(CDbl(AnyDate)) + 2415028
  426.         Else
  427.             TheDay = Fix(CDbl(AnyDate)) + 2415018
  428.         End If
  429.         UTtoJulianDays = TheDay + 0.5 - Remainder
  430.     Else
  431.         UTtoJulianDays = CDbl(AnyDate) + 2415018.5
  432.     End If
  433. End Function
  434. Public Function DaysInMonth(AnyDate As Date) As Integer
  435.     ' returns number of days in a month
  436.     Dim Remainder As Integer
  437.     Dim TheMonth As Integer
  438.     Dim TheYear As Integer
  439.     TheMonth = Month(AnyDate)
  440.     TheYear = Year(AnyDate)
  441.     If TheMonth = 4 Or TheMonth = 6 Or TheMonth = 9 Or TheMonth = 11 Then
  442.         DaysInMonth = 30
  443.         Exit Function
  444.     ElseIf TheMonth = 2 Then
  445.         Remainder = TheYear Mod 4
  446.         If Remainder = 0 Then
  447.             Remainder = TheYear Mod 100
  448.             If Remainder = 0 Then
  449.                 Remainder = TheYear Mod 400
  450.                 If Remainder = 0 Then
  451.                     DaysInMonth = 29
  452.                     Exit Function
  453.                 Else
  454.                     DaysInMonth = 28
  455.                     Exit Function
  456.                 End If
  457.             Else
  458.                 DaysInMonth = 29
  459.                 Exit Function
  460.             End If
  461.         Else
  462.             DaysInMonth = 28
  463.             Exit Function
  464.         End If
  465.     Else
  466.         DaysInMonth = 31
  467.         Exit Function
  468.     End If
  469. End Function
  470. Public Function NextLeapYear(AnyDate As Date) As Integer
  471.     Dim i As Integer
  472.     For i = 1 To 4
  473.         If DaysInMonth(CDate("02/" & Year(AnyDate) + i)) = 29 Then
  474.         NextLeapYear = Year(AnyDate) + i
  475.         Exit Function
  476.     End If
  477. Next
  478. End Function
  479. Public Function DaylightSavingsTime(TheDate As Date) As Boolean
  480.     ' returns True if a given date is within DST limits
  481.     Dim Oct31 As String
  482.     If Month(TheDate) > 10 Or Month(TheDate) < 4 Then
  483.         DaylightSavingsTime = False
  484.         Exit Function
  485.     End If
  486.     
  487.     If Month(TheDate) < 10 And Month(TheDate) > 4 Then
  488.         DaylightSavingsTime = True
  489.         Exit Function
  490.     End If
  491.     
  492.     If Month(TheDate) = 4 Then
  493.         If Day(TheDate) < Weekday(TheDate) Then
  494.             DaylightSavingsTime = False
  495.             Exit Function
  496.         Else
  497.             DaylightSavingsTime = True
  498.             Exit Function
  499.         End If
  500.     End If
  501.     
  502.     If Month(TheDate) = 10 Then
  503.         Oct31 = "10/31/" & Year(TheDate)
  504.         
  505.         If (WeekdayNextLeamok46 TC Long,r2   If (If
  506.   yNex4
  507.         
  508.         If (WeeyNe'm= 1,    Exif
  509.   yNex4
  510.         
  511.  (1el Sg ElseMood If
  512.     
  513.     If Mont (1el Sg Els If
  514. ,   If IfliS4ulianDays(ByVal AnyDate As Date) As Double
  515.     Dim TheDay As Douays(ByVal  ExifAs Doublntee8ear Mod 400
  516.    DVh = 11ifAs Doublntee8ear Mod 400teeoublheDate) = 10  30& Ye_5/.(ightSi:FullMooMonth = 9 Or TheMonth ind 103ElightSavingsTime(TheDate As Date) ny.ulianDays(ByVali        Else
  517.             Dayligh,1 End If
  518.     0  DaynLimie86TheMonth ind 1039v& "  " & _
  519.   f Day(avin9(a4i& " 4f Day(a        If d 4
  520.   e       ianDays(ByVal 9d 4
  521.   e       ianeekdayNextLeamok46 TC Long,r2   IfD - 2415018y.       If d 4
  522.   e       ianDay 4onth 9
  523. End Function
  524. Public Func TC Long,r2   2yx   tLeamok46 TC Long,uble
  525.   e    limit to avFevalue of the )s If
  526.    8x3g,r2mw8F "10/31/" & Year(TheDate)
  527.  8hen ' positive VB dates > 1900
  528. ) = 10  30&