File indexing completed on 2024-04-14 14:11:32

0001 /*
0002     SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <QDateTime>
0010 
0011 #define J2000          2451545.0    //Julian Date for noon on Jan 1, 2000 (epoch J2000)
0012 #define B1950          2433282.4235 // Julian date for Jan 0.9235, 1950
0013 #define SIDEREALSECOND 1.002737909  //number of sidereal seconds in one solar second
0014 
0015 class dms;
0016 
0017 /** @class KStarsDateTime
0018  *@short Extension of QDateTime for KStars
0019  *KStarsDateTime can represent the date/time as a Julian Day, using a long double,
0020  *in which the fractional portion encodes the time of day to a precision of a less than a second.
0021  *Also adds Greenwich Sidereal Time and "epoch", which is just the date expressed as a floating
0022  *point number representing the year, with the fractional part representing the date and time
0023  *(with poor time resolution; typically the Epoch is only taken to the hundredths place, which is
0024  *a few days).
0025  *@note Local time and Local sideral time are not handled here.  Because they depend on the
0026  *geographic location, they are part of the GeoLocation class.
0027  *@note The default timespec is UTC unless the passed value has different timespec value.
0028  *@sa GeoLocation::GSTtoLST()
0029  *@sa GeoLocation::UTtoLT()
0030  *@author Jason Harris
0031  *@author Jasem Mutlaq
0032  *@version 1.1
0033  */
0034 
0035 class KStarsDateTime : public QDateTime
0036 {
0037     public:
0038         /**
0039              *@short Default constructor
0040              *Creates a date/time at J2000 (noon on Jan 1, 200)
0041              *@note This sets the timespec to UTC.
0042              */
0043         KStarsDateTime();
0044 
0045         /**
0046              *@short Constructor
0047              *Creates a date/time at the specified Julian Day.
0048              *@p jd The Julian Day
0049              *@note This sets the timespec to UTC.
0050              */
0051         explicit KStarsDateTime(long double djd);
0052 
0053         /**
0054              *@short Copy constructor
0055              *@p kdt The KStarsDateTime object to copy.
0056              *@note The timespec is copied from kdt.
0057              */
0058         /** @{ */
0059         KStarsDateTime(const KStarsDateTime &kdt);
0060         KStarsDateTime &operator=(const KStarsDateTime &kdt) noexcept;
0061         /** @} */
0062 
0063         /**
0064              *@short Copy constructor
0065              *@p qdt The QDateTime object to copy.
0066              *@note The timespec is copied from qdt.
0067              */
0068         explicit KStarsDateTime(const QDateTime &qdt);
0069 
0070         /**
0071              *@short Constructor
0072              *Create a KStarsDateTimne based on the specified Date and Time.
0073              *@p _d The QDate to assign
0074              *@p _t The QTime to assign
0075              *@p timespec The desired timespec, UTC by default.
0076              */
0077         KStarsDateTime(const QDate &_d, const QTime &_t, Qt::TimeSpec timeSpec = Qt::UTC);
0078 
0079         /**
0080              *Assign the static_cast<long double> Julian Day value, which includes the time of day
0081              *encoded in the fractional portion.
0082              *@p jd the Julian Day value to assign.
0083              */
0084         void setDJD(long double jd);
0085 
0086         /**
0087              *Assign the Date according to a QDate object.
0088              *@p d the QDate to assign
0089              */
0090         void setDate(const QDate &d);
0091 
0092         /**
0093              *Assign the Time according to a QTime object.
0094              *@p t the QTime to assign
0095              *@note timespec is NOT changed even if the passed QTime has a different timespec than current.
0096              */
0097         void setTime(const QTime &t);
0098 
0099         /**
0100              *@return a KStarsDateTime that is the given number of seconds later
0101              *than this KStarsDateTime.
0102              *@p s the number of seconds to add.  The number can be negative.
0103              */
0104         KStarsDateTime addSecs(double s) const;
0105 
0106         /**
0107              *Modify the Date/Time by adding a number of days.
0108              *@p nd the number of days to add.  The number can be negative.
0109              */
0110         inline KStarsDateTime addDays(int nd) const
0111         {
0112             KStarsDateTime kdt(djd() + static_cast<long double>(nd));
0113             kdt.setTimeSpec(timeSpec());
0114             return kdt;
0115         }
0116 
0117         inline bool operator==(const KStarsDateTime &d) const
0118         {
0119             return DJD == d.djd();
0120         }
0121         inline bool operator!=(const KStarsDateTime &d) const
0122         {
0123             return DJD != d.djd();
0124         }
0125         inline bool operator<(const KStarsDateTime &d) const
0126         {
0127             return DJD < d.djd();
0128         }
0129         inline bool operator<=(const KStarsDateTime &d) const
0130         {
0131             return DJD <= d.djd();
0132         }
0133         inline bool operator>(const KStarsDateTime &d) const
0134         {
0135             return DJD > d.djd();
0136         }
0137         inline bool operator>=(const KStarsDateTime &d) const
0138         {
0139             return DJD >= d.djd();
0140         }
0141 
0142         /**
0143              *@return the date and time according to the CPU clock
0144              */
0145         static KStarsDateTime currentDateTime();
0146 
0147         /**
0148              *@return the UTC date and time according to the CPU clock
0149              */
0150         static KStarsDateTime currentDateTimeUtc();
0151 
0152         /**
0153              *@return a KStarsDateTime object parsed from the given string.
0154              *@note This function is format-agnostic; it will try several formats
0155              *when parsing the string.
0156              *@param s the string expressing the date/time to be parsed.
0157              */
0158         static KStarsDateTime fromString(const QString &s);
0159 
0160         /**
0161              *@return the julian day as a long double, including the time as the fractional portion.
0162              */
0163         inline long double djd() const
0164         {
0165             return DJD;
0166         }
0167 
0168         /**
0169              *@return The Greenwich Sidereal Time
0170              *The Greenwich sidereal time is the Right Ascension coordinate that is currently transiting
0171              *the Prime Meridian at the Royal Observatory in Greenwich, UK (longitude=0.0)
0172              */
0173         dms gst() const;
0174 
0175         /**
0176              *Convert a given Greenwich Sidereal Time to Universal Time (=Greenwich Mean Time).
0177              *@p GST the Greenwich Sidereal Time to convert to Universal Time.
0178              */
0179         QTime GSTtoUT(dms GST) const; // FIXME: Shouldn't this be static?
0180 
0181         /**
0182              *@enum EpochType description options
0183              *@note After 1976, the IAU standard for epochs is Julian Years.
0184              */
0185         enum EpochType
0186         {
0187             JULIAN,    /**< Julian epoch (see http://scienceworld.wolfram.com/astronomy/JulianEpoch.html) */
0188             BESSELIAN, /**< Besselian epoch (see http://scienceworld.wolfram.com/astronomy/BesselianEpoch.html) */
0189         };
0190 
0191         /**
0192              *@return the (Julian) epoch value of the Date/Time.
0193              *@short This is (approximately) the year expressed as a floating-point value
0194              *@sa setFromEpoch()
0195              *@note The definition of Julian Epoch used here comes from http://scienceworld.wolfram.com/astronomy/JulianEpoch.html
0196              */
0197         inline double epoch() const
0198         {
0199             return 2000.0 + (djd() - J2000) / 365.25;
0200         }
0201 
0202         /**
0203              *Set the Date/Time from an epoch value, represented as a double.
0204              *@p e the epoch value
0205              *@sa epoch()
0206              */
0207         bool setFromEpoch(double e, EpochType type);
0208 
0209         /**
0210              *Set the Date/Time from an epoch value, represented as a string.
0211              *@p e the epoch value
0212              *@return true if date set successfully
0213              *@sa epoch()
0214              */
0215         bool setFromEpoch(const QString &e);
0216 
0217         /**
0218              *Set the Date/Time from an epoch value, represented as a double.
0219              *@p e the epoch value
0220              *@note This method assumes that the epoch 1950.0 is Besselian, otherwise assumes that the epoch is a Julian epoch. This is provided for backward compatibility, and because custom catalogs may still use 1950.0 to mean B1950.0 despite the IAU standard for epochs being Julian.
0221              *@sa epoch()
0222              */
0223         void setFromEpoch(double e);
0224 
0225         /**
0226              *@short Takes in an epoch and returns a Julian Date
0227              *@return the Julian Date (date with fraction)
0228              *@param epoch A floating-point year value specifying the Epoch
0229              *@param type JULIAN or BESSELIAN depending on what convention the epoch is specified in
0230              */
0231         static long double epochToJd(double epoch, EpochType type = JULIAN);
0232 
0233         /**
0234              *@short Takes in a Julian Date and returns the corresponding epoch year in the given system
0235              *@return the epoch as a floating-point year value
0236              *@param jd Julian date
0237              *@param type Epoch system (KStarsDateTime::JULIAN or KStarsDateTime::BESSELIAN)
0238              */
0239         static double jdToEpoch(long double jd, EpochType type = JULIAN);
0240 
0241         /**
0242              *@short Takes in a string and returns a Julian epoch
0243              */
0244         static double stringToEpoch(const QString &eName, bool &ok);
0245 
0246         /**
0247              * The following values were obtained from Eric Weisstein's world of science:
0248              * http://scienceworld.wolfram.com/astronomy/BesselianEpoch.html
0249              */
0250         constexpr static const double B1900        = 2415020.31352; // Julian date of B1900 epoch
0251         constexpr static const double JD_PER_BYEAR = 365.242198781; // Julian days in a Besselian year
0252     private:
0253         /**
0254              *@return the Greenwich Sidereal Time at 0h UT on this object's Date
0255              *@note used internally by gst() and GSTtoUT()
0256              */
0257         dms GSTat0hUT() const;
0258 
0259         long double DJD { 0 };
0260 };