16 #include <utl/AugerUnits.h>
17 #include <utl/TimeStamp.h>
18 #include <utl/TimeInterval.h>
19 #include <utl/UTCDateTime.h>
20 #include <utl/MoonCycle.h>
21 #include <utl/LeapSeconds.h>
22 #include <utl/ModifiedJulianDate.h>
23 #include <utl/AugerException.h>
24 #include <utl/ErrorLogger.h>
27 #define ul(text) << "\033[4m" << #text << "\033[0m" <<
56 ResetStream(std::istringstream& stream)
65 ValidateStream(std::istringstream& stream,
const std::string& description)
69 if ( stream.fail() ) {
73 ERROR(
"Could not parse " + description +
" \"" + what +
"\"");
80 if ( !what.empty() ) {
81 ERROR(
"Unexpected characters in " + description +
" \"" + what +
"\"");
94 MoonCycleToGPS(
const double& lunation)
99 const double altLunation(lunation + 0.5 + 49.0);
112 result.SetGPSTime(
result.GetGPSSecond() + (
result.GetGPSNanoSecond() > 500e6 ? 1 : 0), 0);
119 fInputFormat = expected;
131 std::istringstream inputStrm(str);
133 if (fInputFormat ==
eMoon) {
135 double moonCycle(-1.0);
136 inputStrm >> moonCycle;
138 if ( !ValidateStream(inputStrm,
"moon cycle") )
141 fTime = MoonCycleToGPS(moonCycle);
143 else if (fInputFormat ==
eUnix) {
145 inputStrm >> unixSec;
147 if ( !ValidateStream(inputStrm,
"Unix timestamp") )
152 unsigned long GPSsec(0);
163 if (fInputFormat ==
eNone || fInputFormat ==
eUTC) {
177 inputStrm >> year >> dash1 >> month >> dash2 >> day >> tee >> hour >> colon1 >> minute
178 >> colon2 >> second >>
what;
180 if (!what.empty() && what !=
"Z") {
182 ERROR(
"Unexpected characters in UTC timestamp \"" + what +
"\"");
187 if (fInputFormat ==
eNone) {
191 ResetStream(inputStrm);
200 if (fInputFormat ==
eUTC) {
201 if (dash1 ==
'?' || (dash1 ==
'-' && dash2 ==
'?')) {
202 ResetStream(inputStrm);
205 ERROR(
"UTC timestamp \"" + what +
"\" not given to sufficient precision (at least"
209 if (dash1 !=
'-' || dash2 !=
'-' || (tee !=
'?' && tee !=
'T') || (colon1 !=
'?'
210 && colon1 !=
':') || (colon2 !=
'?' && colon2 !=
':')) {
211 ResetStream(inputStrm);
214 ERROR(
"Could not parse UTC timestamp \"" + what +
"\"");
230 if (fInputFormat ==
eGPS) {
235 if ( !ValidateStream(inputStrm,
"GPS second timestamp") )
252 if (fInputFormat ==
eUTC)
278 std::cout << std::fixed << std::setprecision(7)
285 std::cout << unixSec << std::endl;
290 std::cout << std::fixed << std::setprecision(5)
307 help(
char*& execPath,
const int& exitCode)
310 char* execBase( strrchr(execPath,
'/') );
317 std::cout <<
"Usage: " << execBase <<
" [" ul(OPTION)
"]... [" ul(TIMESTAMP)
"]\n"
318 <<
"Unless the interpretation of " ul(TIMESTAMP)
" is made explicit with an option, it is\n"
319 <<
"assumed to be either a GPS second timestamp or a UTC timestamp in ISO 8601\n"
320 <<
"format (eg, YYYY-MM-DDTHH:MM:SSZ) given to at least the day.\n"
321 <<
"Unless the desired output format is chosen with an option, it will be GPS\n"
322 <<
"second if the input was UTC, and UTC in all other cases.\n"
326 <<
" -d Dump the Offline leap second table and exit, ignoring " ul(TIMESTAMP)
".\n"
327 <<
" -M Interpret " ul(TIMESTAMP)
" as a full moon cycle in the January 2004 epoch (ie,\n"
328 <<
" full moon at 0.0, new moon at 0.5, and so on). Note that moon cycle skips\n"
329 <<
" leap seconds.\n"
330 <<
" -m Print output as full moon cycle in the January 2004 epoch.\n"
331 <<
" -j Print output as Modified Julian Date (days since 1858-11-17 UTC).\n"
332 <<
" -U Interpret " ul(TIMESTAMP)
" as a Unix timestamp (seconds since 1970-01-01 UTC).\n"
333 <<
" Note that Unix time skips leap seconds.\n"
334 <<
" -u Print output as Unix timestamp.\n"
336 <<
"With no " ul(TIMESTAMP)
" parameter, timestamps will be read from stdin. If multiple\n"
337 <<
"times are provided via stdin, then they must all be of the same format (eg,\n"
338 <<
"they must all be GPS second timestamps, or all UTC timestamps, etc).\n";
349 while ( (opt = getopt(argc, argv,
":dhMmjUu")) != -1 ) {
351 case 'd': parse.Dump();
return 0;
352 case 'h':
return help(argv[0], 0);
358 case '?':
ERROR(std::string(
"Unrecognised option -") +
char(optopt));
return 2;
359 case ':':
ERROR(std::string(
"Expected an argument for option -") +
char(optopt));
return 2;
367 else if (optind == argc - 1)
370 ERROR(
"Too many input parameters. To convert multiple timestamps you must "
371 "pass them over stdin (ie, pipe them into this program)");
376 bool hadErrors(
false);
377 for (std::string token; readParam || std::cin >> token; ) {
380 token = argv[argc - 1];
double ModifiedJulianDate(const time_t unixSecond)
void SetInputFormat(Format expected)
A TimeStamp holds GPS second and nanosecond for some event.
Exception for reporting variable out of valid range.
void SetGPSTime(const unsigned long sec, const double nsec=0)
Set GPS second and (optionally) nanosecond.
int main(int argc, char *argv[])
void SetOutputFormat(Format expected)
bool ReadStrToTime(std::string &str)
bool ConvertGPSToUnix(const unsigned long gpsSecond, time_t &unixSecond) const
returns true if the GPS second is an UTC leap second
double GetLunation(const LunationType type=eFullMoon, const LunationEpoch epoch=eJan2004) const
A TimeInterval is used to represent time elapsed between two events.
utl::LeapSeconds & fLeapSeconds
unsigned long GetGPSSecond() const
GPS second.
const utl::UTCDateTime epoch(2000, 1, 6, 14, 20, 30)
void Dump(const FEvent &fevent)
const double kMeanSynodicMonth(29.530589)
std::string GetInXMLFormat() const
#define ERROR(message)
Macro for logging error messages.
TimeStamp GetTimeStamp() const
const std::string & GetMessage() const
Retrieve the message from the exception.
void ConvertUnixToGPS(const time_t unixSecond, unsigned long &gpsSecond) const
const utl::TimeInterval interval(altLunation *kMeanSynodicMonth *utl::day)