//# MVTime.cc: Class to handle date/time type conversions and I/O //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003,2004,2008 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ //# Includes #include #include #include #include #include #include #include #include #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN // MVTime class //# Static members MVTime::Format MVTime::defaultFormat = MVTime::Format(); MVTime::Format MVTime::interimFormat = MVTime::Format(); Bool MVTime::interimSet = False; //# Constructors MVTime::MVTime() : val(0){} MVTime::MVTime(Double d) : val(d){} MVTime::MVTime(const Time &other) : val(other.modifiedJulianDay()){} MVTime::MVTime(const MVEpoch &other) : val(other.get()){} MVTime::MVTime(Int yy, Int mm, Double dd, Double d) { if (mm < 3) { yy--; mm += 12; } dd += d; Int b = 0; if (yy>1582 || (yy==1582 && (mm>10 || (mm==10 && dd >= 15)))) { b = ifloor(yy/100.); b = 2 - b + (Int)(b/4); } val = ifloor(365.25*yy) + ifloor(30.6001*(mm+1)) + dd - 679006.0 +b; } MVTime::MVTime(const MVTime &other) : val(other.val) {} MVTime::MVTime(const Quantity &other) { val = other.getBaseValue(); if (other.check(UnitVal::ANGLE)) { val /= C::circle; } else { other.assure(UnitVal::TIME); val /= C::day; } } MVTime &MVTime::operator=(const MVTime &other) { if (this != &other) { val = other.val; } return *this; } // Destructor MVTime::~MVTime() {} // Operators MVTime::operator Double() const { return val; } // Member functions Double MVTime::day() const { return val; } Double MVTime::hour() const { return val*24.; } Double MVTime::minute() const { return val*24.*60.; } Double MVTime::second() const { return val*24.*3600.; } Quantity MVTime::get() const { return Quantity(val,"d"); } Quantity MVTime::get(const Unit &inunit) const { if (inunit.getValue() == UnitVal::TIME) { return Quantity(val, "d").get(inunit); } return Quantity(val*C::circle,"rad").get(inunit); } Time MVTime::getTime() const { return Time(val+2400000.5); } const String &MVTime::dayName(uInt which) { static const String weekDay[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; AlwaysAssert(which > 0 && which < 8, AipsError); return weekDay[which-1]; } const String &MVTime::dayName() const { return (dayName(weekday())); } const String &MVTime::monthName(uInt which) { static const String mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; return mon[which-1]; } const String &MVTime::monthName() const { return (monthName(month())); } uInt MVTime::weekday() const { return ((ifloor(val+2.)%7 + 7)%7 + 1); } uInt MVTime::month() const { Int c,e,a; ymd(c,e,a); return e; } uInt MVTime::monthday() const { Int c,e,a; ymd(c,e,a); return a; } Int MVTime::year() const { Int c,e,a; ymd(c,e,a); return c; } Int MVTime::ymd() const { Int c,e,a; ymd(c,e,a); if (c < 0) { return -(abs(c)*10000 + e*100 + a); } return (c*10000 + e*100 + a); } uInt MVTime::yearday() const { Int c,e,a; ymd(c,e,a); if (c%4 == 0 && (c%100 != 0 || c%400 == 0)) { c = (e+9)/12; } else { c = 2 * ((e+9)/12); } return ((275*e)/9 - c + a - 30); } uInt MVTime::yearweek() const { Int yd(yearday()-4); uInt yw((yd+7)/7); yd %= 7; // Check for other week if (yd >= 0) { if (yd >= (Int)weekday()) return yw+1; } else if (yd+7 >= (Int)weekday()) return yw+1; return yw; } void MVTime::ymd(Int &yyyy, Int &mm, Int &dd) const { Int z = ifloor(val + 2400001.0); dd = z; if (z >= 2299161) { Long al = ifloor(((Double) z - 1867216.25)/36524.25); dd = z + 1 + al - (Int)(al/4); } dd += 1524; // tmp introduced to circumvent optimization problem with gcc2.7.2.1 // on the DecAlpha Int tmp = ifloor((dd - 122.1)/365.25); yyyy = tmp; Int d = ifloor(365.25 * tmp); mm = tmp = ifloor((dd - d)/30.6001); dd -= d + ifloor(30.6001 * tmp); // day if (mm < 14) { // month mm--; } else { mm -= 13; } yyyy -= 4715; // year if (mm > 2) yyyy--; } MVTime::Format MVTime::setFormat(MVTime::formatTypes intyp, uInt inprec) { Format tmp = MVTime::defaultFormat; MVTime::defaultFormat.typ = intyp; MVTime::defaultFormat.prec = inprec; MVTime::interimSet = False; return tmp; } MVTime::Format MVTime::setFormat(uInt intyp, uInt inprec) { return setFormat((MVTime::formatTypes) intyp, inprec); } MVTime::Format MVTime::setFormat(uInt inprec) { return setFormat(MVTime::TIME, inprec); } MVTime::Format MVTime::setFormat(const MVTime::Format &form) { Format tmp = MVTime::defaultFormat; MVTime::defaultFormat = form; MVTime::interimSet = False; return tmp; } MVTime::Format MVTime::getFormat() { return MVTime::defaultFormat; } MVTime::formatTypes MVTime::giveMe(const String &in) { const Int N_name = 32; static const String tab[N_name] = { "ANGLE", "TIME", "CLEAN", "NO_D", "NO_DM", "YMD", "DMY", "MJD", "DAY", "NO_TIME", "DIG2", "FITS", "LOCAL", "USE_SPACE", "ALPHA", "USE_Z", "ISO", "BOOST", "NO_H", "NO_HM", "ANGLE_CLEAN", "ANGLE_NO_D", "ANGLE_NO_DM", "ANGLE_CLEAN_NO_D", "ANGLE_CLEAN_NO_DM", "TIME_CLEAN", "TIME_NO_H", "TIME_NO_HM", "TIME_CLEAN_NO_H", "TIME_CLEAN_NO_HM", "YMD_ONLY", "MOD_MASK" }; static const MVTime::formatTypes nam[N_name] = { MVTime::ANGLE, MVTime::TIME, MVTime::CLEAN, MVTime::NO_D, MVTime::NO_DM, MVTime::YMD, MVTime::DMY, MVTime::MJD, MVTime::DAY, MVTime::NO_TIME, MVTime::DIG2, MVTime::FITS, MVTime::LOCAL, MVTime::USE_SPACE, MVTime::ALPHA, MVTime::USE_Z, MVTime::ISO, MVTime::BOOST, MVTime::NO_H, MVTime::NO_HM, MVTime::ANGLE_CLEAN, MVTime::ANGLE_NO_D, MVTime::ANGLE_NO_DM, MVTime::ANGLE_CLEAN_NO_D, MVTime::ANGLE_CLEAN_NO_DM, MVTime::TIME_CLEAN, MVTime::TIME_NO_H, MVTime::TIME_NO_HM, MVTime::TIME_CLEAN_NO_H, MVTime::TIME_CLEAN_NO_HM, MVTime::YMD_ONLY, MVTime::MOD_MASK }; Int t = MUString::minimaxNC(in, N_name, tab); return (t 1000) { // New FITS format dd = dd2; } else { if (dd2 < 50) { dd2 += 2000; } else if (dd2 < 100) { dd2 += 1900; } dd = r; // Swap day/year r = dd2; } } else if (in.testChar('/')) { if (in.freqChar('/') > 1) { in.skipChar(); if (in.testChar('/')) { in.skipChar(); mm = 1; } else { mm = in.getuInt(); if (!in.tSkipChar('/')) { return MVAngle::handleReadError (in, throwExcp); } } dd = in.getDouble(); } else { tp = 1; } } else { return MVAngle::handleReadError (in, throwExcp); } if (in.tSkipChar('/') || in.tSkipChar('-') || in.tSkipChar(' ')) { if (MVAngle::read(res, in, chk)) { res = Quantity(res.get("deg").getValue()/360., "d"); } else { return MVAngle::handleReadError (in, throwExcp); } } else if (in.tSkipChar('T')) { // new FITS/ISO if (MVAngle::read(res, in, False)) { res = Quantity(res.get("deg").getValue()/360., "d"); // Allow possible time zone as in ISO-8601 if (in.testChar('+') || in.testChar('-')) { Double s = in.getSign(); Double r = in.getuInt(); if (in.tSkipChar(':')) { r += Double(in.getuInt())/60.0; } res -= Quantity(s*r/24.0,"d"); // Time zone } else { in.tSkipChar('Z'); // accept FITS/ISO UTC } } else { return MVAngle::handleReadError (in, throwExcp); } } if (tp == 0) { res += MVTime(r, mm, dd).get(); } else { res += r; } } res *= s; // Sign if (chk) { in.skipBlank(); if (!in.eos()) { return MVAngle::handleReadError (in, throwExcp); // not fully consumed } } in.unpush(); return True; } Bool MVTime::read(Quantity &res, const String &in, Bool chk) { return read (res, in, chk, False); } Bool MVTime::read(Quantity &res, const String &in, Bool chk, Bool throwExcp) { MUString tmp(in); // Pointed non-const String if (!MVTime::read(res, tmp, chk, throwExcp)) { Double r = tmp.getDouble(); UnitVal u; String us; if (!MVAngle::unitString(u,us,tmp)) { return MVAngle::handleReadError (tmp, throwExcp); } if (u == UnitVal::NODIM) { res = Quantity(r,"d"); } else if (u == UnitVal::TIME) { res = Quantity(r,us); } else if (u == UnitVal::ANGLE) { res = Quantity(Quantity(r/C::_2pi,us).getBaseValue(), "d"); } else { return MVAngle::handleReadError (tmp, throwExcp); } } return True; } ostream &operator<<(ostream &os, const MVTime &meas) { if (MVTime::interimSet) { MVTime::interimSet = False; meas.print(os, MVTime::interimFormat); } else { meas.print(os, MVTime::defaultFormat); } return os; } istream &operator>>(istream &is, MVTime &meas) { String str; is >> str; if (ios::failbit & is.rdstate()) return is; Quantity t; if (MVTime::read(t, str)) { meas = MVTime(t).get(); } else { is.clear(ios::failbit | is.rdstate()); } return is; } ostream &operator<<(ostream &os, const MVTime::Format &form) { MVTime::interimFormat = form; MVTime::interimSet = True; return os; } } //# NAMESPACE CASACORE - END