![]() |
![]() |
|
![]() |
Paradox® Date, Time, and DateTime Data Types Basic Astronomy and Time Types © 2001 Rick Kelly www.crooit.com Download the library containing the routines used in this series. Preface A library of all OPAL methods presented is available here. In the previous section of exploring Paradox Date and Time values we presented some common arithmetical tasks involving Date types. Now we will take a look at time and some basic astronomy involving dates and times. Time Before we explore some common arithmetical tasks involving Time types, here are some constants we will be using. Const cnOneDay = 86400000.0 ;Milliseconds in a day cnOneHour = 3600000.0 ;Milliseconds in a hour cnOneMinute = 60000.0 ;Milliseconds in a minute cnOneSecond = 1000.0 ;Milliseconds in a second endConstTime types internally are stored as a number representing the number of milliseconds since midnight with values in the range 0-86,399,999 for a total of 86,400,000 milliseconds in a day. Our constants represent whole and portions of a day and are cast as Number types to support DateTime type calculations. Given separate Date and Time types, it is easy to generate a DateTime type. The date portion is extracted in fixed format (uncorrected for B.C. dates), multiplied by the number of milliseconds in one day and the fixed format time added in. method emDateTime(daAny Date,tiAny Time) DateTime ; ; Given Date and Time Types, return a DateTime Type ; return datetime((number(daAny) * cnOneDay) + number(tiAny)) endMethodOur method that builds Time types will have a few extra capabilities that we can use later on. Given separate hours, minutes, seconds and milliseconds, the method will return the number of days in addition to a Time type. Having the days included will allow us to accept input values that are outside the normal range of 0-23 for hours and 0-59 for minutes/seconds and 0-999 for milliseconds. This will support applications that keep track of time in hours, minutes, seconds, or milliseconds as well as handling calculations that wrap past midnight. method emTime(liHour LongInt, liMinute LongInt, liSecond LongInt, liMillisecond LongInt, var liDays LongInt) Time ; ; Given hour,minute,second,millisecond ; return a Time type ; ; liDays is used to indicate the total number ; of days ; ; Negative values are assumed to be positive ; var dtTotalTime DateTime endVar dtTotalTime = dateTime(abs(liHour) * cnOneHour + abs(liMinute) * cnOneMinute + abs(liSecond) * cnOneSecond + abs(liMillisecond)) ; ; Extract the number of days ; liDays = longInt(date(dtTotalTime)) return time(dtTotalTime) endMethodAn additional way to use the method emTime is to add some measure of time to another. For instance, to add 30 minutes to the current time: var tiCurrentTime Time liElaspedDays LongInt endVar tiCurrentTime = time() msgInfo(tiCurrentTime, emTime(hour(tiCurrentTime), minute(tiCurrentTime) + 30, second(tiCurrentTime), milliSec(tiCurrentTime), liElaspedDays))Let’s calculate the elapsed time between two Time types taking advantage of what we know about Time type internal format, adjusting the calculations when the ending time is prior to the starting time by adding one day in milliseconds that addresses the midnight wrapover. method emElaspedTime(tiStartTime Time,tiEndTime Time) Time var liStartingTime LongInt liEndingTime LongInt endVar liStartingTime = longInt(tiStartTime) liEndingTime = longInt(tiEndTime) ; ; Calculate the Time difference between two Time types ; switch ; ; Check for ending time < starting time ; case liEndingTime < liStartingTime : liEndingTime = liEndingTime + longInt(cnOneDay) endSwitch return time(liEndingTime - liStartingTime) endMethod Basic Astronomy Before we get into some calculations, let’s go over some basic concepts. I'm no astronomer, so my perceptions are strictly from an amateur (likely more basic than even that!) perspective as my interest only extends to what is necessary to know for calendaring. Imagine the earth inside and at the center of a large beach ball with all the stars and other objects positioned on the inside surface of this ball and imagine you have a 360º view of the entire inside surface in all directions. Astronomers refer to the stars and other objects by their position within this celestial sphere. On Earth, positions are calculated using longitude and latitude. If we take those lines of latitude and longitude and extend them outward and place them on the inside of our beach ball, a coordinate grid system is created that can be used for location with some important differences - stars and other objects are in continual motion within the celestial sphere and with respect to each other and the coordinates slowly change position over time due to a shift in the Earth’s orientation in the celestial sphere known as precession. In our celestial sphere, positions are calculated using declination (latitude) and right ascension (longitude) and are documented in atlases usually accompanied by a year such as 2000 for which the references tables are strictly correct. Many calculations use algorithms based on reference tables as of a particular year and project past and future positions accordingly. In our calculations we will be using the reference date of January 1, 2000 documented by procedure cmJ2000. Declination is usually specified in degrees 0-360. Because the Earth’s rotation gives the appearance of the celestial sphere rotating around Earth once every 24 hours, right ascension is usually specified in hours 0 to 24 around the sky. Both declination and right ascension are further graduated using base 60 arithmetic into arcminutes and arcseconds each 1/60th in value. Astronomical Date and Time Astronomers specify date and time in a fixed number format referred to as "julian days" or "julian astronomical days." The starting point for counting both forward and backward from in use today was adapted in the nineteenth century as November 24, -4713 (January 1, -4713 on the Julian calendar) at 12:00:00 PM (Noon).1 (Page 12) As our resident Paradox Goddess Liz Woodhouse once asked me about those "star dates," let’s refer to these units of time as "Star Dates," Captain Kirk. (All astronomers can start cringing.) Star Dates are floating point numbers with the fractional part representing a portion of a 24 hour solar day. The calculation of our starting point (Star Date of zero) is: New Constants we will be referring to are:emFixedFromGregorian(date(11,24,-4713)) + .5where .5 = 12:00:00 PM (Noon) Const ; November 24, -4713 at Noon cnStarDateStart = -1721424.5 endConstAnother definition we will use is a close derivative of Star Dates we will call a Star Moment where the fixed days portion is adjusted to our fixed date format. This will also be a floating point number with the fractional part representing a portion of a solar day of 24 hours. An example of these values and their relationship using June 1, 2001 at 12:00:00 (Noon): The days portion (730,637) of nuStarMoment is equivalent to the fixed date returned from emFixedFromGregorian for June 1, 2001 so we deduce that given Paradox Date and Time types, we can calculate a Star Moment as :nuStarDate = number(emFixedFromGregorian(date(6,1,2001)) - cnStarDateStart + .5Result: 2,452,062.0 and converting a Star Moment to Paradox Date and Time types:number(emFixedFromGregorian(date(6,1,2001))) + number(time("12:00:00 PM")) / cnOneDaySee cmMomentFromDateTime daAny = emGregorianFromFixed(longInt(cmFloor(nuStarMoment))) tiAny = time(nuStarMoment.fraction() * cnOneDay)See cmMomentToDateTime Sunrise and Sunset In our example of calculating Sunrise/Sunset, there are other astronomical and spherical trigonometry concepts not discussed in this article (I like the Equation of Time and you are encouraged to spend a pleasant evening browsing the web where many articles and examples can be found and/or review the references cited. Having a beach ball handy during this browsing worked for me. <g>). The core calculations are done using Star Dates and Universal Time (UTC). UTC is the time at longitude 0 and sometimes is referred to as Greenwich Mean Time or Zulu Time (Aviation). UTC time results are adjusted for local times using cmLocalFromUniversal. The precision of our calculations is within about +- 10 minutes and adjustments for criteria such as atmospheric refraction and location altitude are not included. Location Latitude and Longitude are expressed as decimal degrees and the following method emDecimalDegrees is provided as a conversion aid. North Latitude and West Longitude are assumed to be positive and South Latitude and East Longitude are assumed to be negative. method emDecimalDegrees(siDegrees SmallInt, siMinutes SmallInt, nuSeconds Number) Number ; ; Given Degrees,Minutes, and Seconds ; return in decimal form (xx.xxxx) ; ; No error checking for values out of ; normal range of 0-359 for siDegrees, ; 0-59 for siMinutes and nuSeconds ; return number(siDegrees) + (number(siMinutes) / 60) + (nuSeconds / 3600) endMethodAdditional constants referred to are: const cnSunRise = 1.0 cnSunSet = -1.0 endConstIn our example, we be will using Anchorage (61º 12" N, 149º 54" W), Alaska as our location on June 30, 2001. method emSunRiseOrSet(daAny Date, nuLatitude Number, nuLongitude Number, nuTimeZoneHours Number, nuRiseOrSet Number) DateTime ; ; Return Sun Rise time for given date daAny ; ; nuTimeZoneHours is received in hours and ; converted to minutes ; ; nuRiseOrSet = +1 for Sunrise ; = -1 for Sunset ; ; Latitude/Longitude is given in decimal degrees ; and positive for north/west and ; negative for south/east respectively ; var nuMoment Number endVar ; ; Cast daAny as a Star Moment at Midnight ; nuMoment = number(emFixedFromGregorian(daAny)) ; ; Calculate Sunrise/Sunset and return DateTime Type ; return cmMomentToDateTime(cmCalcSunRiseOrSet(nuMoment, nuLatitude, nuLongitude, nuTimeZoneHours * 60, nuRiseOrSet)) endMethodSunrise for Anchorage, Alaska on June 30, 2001 var daAny Date nuLatitude Number nuLongitude Number nuTimeZoneHours Number dtSunRiseOrSet DateTime endVar daAny = date(6,30,2001) nuLatitude = emDecimalDegrees(61,12,0) nuLongitude = emDecimalDegrees(149,54,0) nuTimeZoneHours = -9 dtSunRiseOrSet = emSunRiseOrSet(daAny, nuLatitude, nuLongitude, nuTimeZoneHours, cnSunRise)Result: dtSunRiseOrSet = June 30, 2001 at 03:26:41 AM local time Anchorage, Alaska observes Daylight Savings. Adding one hour to the returned time will address this for June 30, 2001, and, now the OPAL call looks like : dtSunRiseOrSet = emSunRiseOrSet(daAny, nuLatitude, nuLongitude, nuTimeZoneHours, cnSunRise) switch case emDaylightSavingsStart(year(daAny)) > daAny : case emDaylightSavingsEnd(year(daAny)) > daAny : dtSunRiseOrSet = dtSunRiseOrSet + cnOneHour endSwitchResult: dtSunRiseOrSet = June 30, 2001 at 04:26:41 AM local time Sunset for Anchorage, Alaska is calculated in similar fashion by changing the last parameter passed. dtSunRiseOrSet = emSunRiseOrSet(daAny, nuLatitude, nuLongitude, nuTimeZoneHours, cnSunSet) switch case emDaylightSavingsStart(year(daAny)) > daAny : case emDaylightSavingsEnd(year(daAny)) > daAny : dtSunRiseOrSet = dtSunRiseOrSet + cnOneHour endSwitchResult: dtSunRiseOrSet = June 30, 2001 at 11:39:13 PM local time Checking our calculations at the U.S. Naval Observatory shows Sunrise at 04:27 AM and Sunset at 11:40 PM. Paradox rules! Conclusion We now have methods that support some common arithmetical time calculations, including an introduction to basic astronomy using Date and Time types all of which showcase the many capabilities for Date and Time Paradox supports. Next: More B.C. Date Tips and Tricks References Common / Shared ObjectPAL® Routines Discussion of this article |
![]() Feedback | Paradox Day | Who Uses Paradox | I Use Paradox | Downloads ![]() |
|
![]() The information provided on this Web site is not in any way sponsored or endorsed by Corel Corporation. Paradox is a registered trademark of Corel Corporation. ![]() |
|
![]() Modified: 15 May 2003 Terms of Use / Legal Disclaimer ![]() |
![]() Copyright © 2001- 2003 Paradox Community. All rights reserved. Company and product names are trademarks or registered trademarks of their respective companies. Authors hold the copyrights to their own works. Please contact the author of any article for details. ![]() |
![]() |
|