How to get UTC offset from string - c++

I'm getting string like 2015-04-29 15:36:16.5761891 +03:00. I can easily exctract the date using std::get_time.
std::tm time;
std::string stringTime = "2015-04-29 15:36:16.5761891 +03:00";
std::istringstream stringStream(stringTime);
stringStream >> std::get_time(&time, "%Y-%m-%d %H:%M:%S");
cout << time.tm_year << endl;
cout << time.tm_mon << endl;
cout << time.tm_mday << endl;
cout << time.tm_hour << endl;
cout << time.tm_min << endl;
cout << time.tm_sec << endl;
It's working fine for me. Now how can I extract UTC offset from this string?

You can just keep on reading like this:
#include <ctime>
#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>
int main()
{
std::tm time;
std::string stringTime = "2015-04-29 15:36:16.5761891 +03:00";
std::istringstream stringStream(stringTime);
std::string decimals;
std::string offset;
stringStream >> std::get_time(&time, "%Y-%m-%d %H:%M:%S") >> decimals >> offset;
std::cout << time.tm_year << '\n';
std::cout << time.tm_mon << '\n';
std::cout << time.tm_mday << '\n';
std::cout << time.tm_hour << '\n';
std::cout << time.tm_min << '\n';
std::cout << time.tm_sec << '\n';
std::cout << decimals << '\n';
std::cout << offset << '\n';
}
Output:
115
3
29
15
36
16
.5761891
+03:00

Related

convert one date format into another date format does not work c++

Hello I want to convert this dateformat
2022-11-17T112139.568+0100
into this dateformat
2022-11-17 11:21:39
This is my code
int main(int argc, char* argv[]){
std::string testString = "2022-11-17T112139.568+0100";
struct tm source ;
strptime(testString.c_str(), "%y-%M-%dT%H%m%s.%S%Z", &source);
std::cout << "Second: " << source.tm_sec << std::endl;
std::cout << "Minute: " << source.tm_min << std::endl;
std::cout << "Hour: " << source.tm_hour << std::endl;
std::cout << "Day: " << source.tm_mday << std::endl;
std::cout << "Month: " << source.tm_mon <<std::endl;
std::cout << "Year: " << source.tm_year << std::endl;
char dest[20];
strftime(dest, sizeof(dest), "%y-%M-%d %H:%m:%s", &source);
std::cout << "Output: " << dest << std::endl;
return 0;
}
and this is the output:
Second: 1
Minute: 0
Hour: -421736992
Day: 32767
Month: 6299080
Year: 120
Output: 20-00-32767
How can I convert one dateformat into another date format in c++?
i also tried the boost library but that did not work either
Indeed I had a wrong source for formating string.
This works now:
int main(int argc, char* argv[]){
std::string testString = "2022-11-17T112139.568+0100";
struct tm source ;
strptime(testString.c_str(), "%Y-%m-%dT%H%M%S.%FFF%Z", &source);
std::cout << "Second: " << source.tm_sec << std::endl;
std::cout << "Minute: " << source.tm_min << std::endl;
std::cout << "Hour: " << source.tm_hour << std::endl;
std::cout << "Day: " << source.tm_mday << std::endl;
std::cout << "Month: " << source.tm_mon <<std::endl;
std::cout << "Year: " << source.tm_year << std::endl;
char dest[20];
strftime(dest, sizeof(dest), "%Y-%m-%d %H:%M:%S", &source);
std::cout << "Output: " << dest << std::endl;
return 0;
}

Input File Reading Just Repeats First Data Line from 1 of 2 Files

I'm working on a project. The idea is that it has two input files, we'll call them TimeFile and FullFile.
TimeFile gives two timestamps in the format:
DD-MM-YY HH:MM:SS DD-MM-YY HH:MM:SS
And FullFile is in the format of a timestamp and some data:
YYYY-MM-DD HH:MM:SS Value Error Error
The idea is that the program reads the timestamps from TimeFile, then goes through all the lines in FullFile, and if it finds a timestamp from FullFile that lands between two from TimeFile, it copies the whole line into a new smaller data file. In essence, I want to go from one gigantic data file to a bunch of smaller data files divided up by time intervals.
Needless to say, it doesn't work. It does most of what I want, but the resulting smaller data files are always empty.
The strange part is why. It appears to read the timestamps from TimeFile just fine, but it screws up reading from FullFile and just reads the first line over and over again. I don't really have a solid idea why either, best I can determine is that they're reading the same way, but one works and the other doesn't.
#include <cmath>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <tuple>
#include <vector>
#include <stdio.h>
#include <math.h>
#include <complex>
#include <stdint.h>
#include <time.h>
#include <string.h>
int main(){
//Read Run-Times-File - Cycle 1
std::ifstream TimeFile;
TimeFile.open("jet_run_times.dat");
if(!TimeFile.good()){
std::cout << "TimeFile Didn't Work" << std::endl;
return 1;
}
//Read Full-File - Cycle 2
std::ifstream FullFile;
FullFile.open("jet_full.txt");
if(!FullFile.good()){
std::cout << "FullFile Didn't Work" << std::endl;
return 1;
}
std::cout << "Both Files Worked" << std::endl;
std::ofstream results;
//Initial Time - A ; Final Time - B ; Jet Pressure Time - C
int iday, ihour, imin, isec, fday, fhour, fmin, fsec, imon, fmon;
char dash, colon ;
std::string imonth, fmonth ;
//std::ostringstream temp;
int run = 0;
int year, month, day , hour, min;
double sec, value, neg, pos, AfterStart, BeforeEnd;
for(int i = 0 ; i < 192 ; i++) {
//Cycle 1
//Write jet_run_XXX.txt
run++;
std::ostringstream temp;
if(run <= 9) temp << "jet_run_00" << run << ".txt" ;
if( (run >= 10) && (run <= 99) ) temp << "jet_run_0" << run << ".txt" ;
if(run >= 100) temp << "jet_run_" << run << ".txt" ;
results.open(temp.str());
std::cout << temp.str() << " File Made" << std::endl;
TimeFile >> iday >> dash >> imonth >> ihour >> colon >> imin >> colon >> isec >> fday >> dash >> fmonth >> fhour >> colon >> fmin >> colon >> fsec;
/*
std::cout << "iday " << iday << std::endl;
std::cout << "dash " << dash << std::endl;
std::cout << "imonth " << imonth << std::endl;
std::cout << "ihour " << ihour << std::endl;
std::cout << "colon " << colon << std::endl;
std::cout << "imin " << imin << std::endl;
std::cout << "isec " << isec << std::endl;
std::cout << "fday " << fday << std::endl;
std::cout << "dash " << dash << std::endl;
std::cout << "fmonth " << fmonth << std::endl;
std::cout << "fhour " << fhour << std::endl;
std::cout << "colon " << colon << std::endl;
std::cout << "fmin " << fmin << std::endl;
std::cout << "fsec " << fsec << std::endl;
*/
if( imonth == "Apr-22") imon = 4;
if( fmonth == "Apr-22") fmon = 4;
if( imonth == "May-22") imon = 5;
if( fmonth == "May-22") fmon = 5;
/*
std::cout << "imon " << imon << std::endl;
std::cout << "fmon " << fmon << std::endl;
*/
//Cycle 2
for(int j = 0 ; j < 5833 ; j++){
FullFile >> year >> dash >> month >> dash >> day >> hour >> colon >> min >> colon >> sec >> value >> neg >> pos;
std::cout << j << std::endl;
/*
std::cout << "year " << year << std::endl;
std::cout << "dash " << dash << std::endl;
std::cout << "month " << month << std::endl;
std::cout << "dash " << dash << std::endl;
std::cout << "day " << day << std::endl;
std::cout << "hour " << hour << std::endl;
std::cout << "colon " << colon << std::endl;
std::cout << "min " << min << std::endl;
std::cout << "sec " << sec << std::endl;
std::cout << "value " << value << std::endl;
std::cout << "neg " << neg << std::endl;
std::cout << "pos " << pos << std::endl;
*/
//Set-Up the Check if A <= C <= B
AfterStart = (sec - isec) + (min - imin)*100 + (hour - ihour)*10000 + (day - iday)*1000000 + (month - imon)*100000000;
BeforeEnd = (fsec - sec) + (fmin - min)*100 + (fhour - hour)*10000 + (fday - day)*1000000 + (fmon - month)*100000000;
std::cout << "AfterStart " << AfterStart << std::endl;
std::cout << "BeforeEnd " << BeforeEnd << std::endl;
//If A <= C <= B, copy all of C to jet_run_XXX.txt
if ( (AfterStart >= 0.0) && (BeforeEnd >= 0.0) ){
results << year << dash << month << dash << day << " " << hour << colon << min << colon << sec << " " << value << " " << pos << " " << neg << '\n' << std::endl;
std::cout << "Got One!" << std::endl;
}
}
//End Cycle 2
results.close();
}
//End Cycle 1
return 0;
}
I'm stumped, any help would be appreciated.
Edit: Thinking it might help if I give a few lines of each of my data files to see if it's a formatting issue, so here's the first 3 lines of each:
TimeFile
03-Apr-22 22:42:19 03-Apr-22 22:56:13
03-Apr-22 22:58:25 03-Apr-22 23:15:14
03-Apr-22 23:17:23 03-Apr-22 23:35:32
FullFile
2022-04-13 12:39:37.500000000 70.00000 0.0 0.0
2022-04-13 12:43:52.500000000 70.00000 0.0 0.0
2022-04-13 12:48:07.500000000 70.00000 0.0 0.0
Edit2:- Important discovery. Running this code with that block uncommented out reproduces the data in the line but instead of 70 0 0 you get 1 0 43.1495 for the last three values. GetLine doesn't seem to do this but I'm having trouble understanding how to cut that open.
Not entirely sure what this means beyond that somehow that's not reading those values properly but when I try to account for a tab it's not an improvement.

Convert string into hex format and append "0x " to hex value

I need to convert string to hex format and append "0x" prefix to hex value.
For Example:
Input: std::string s = "0x06A4";
Output: int num = 0x06A4
I have tried this code:
{
std::stringstream ss;
std::string s = "0x06A4";
int num = std::stoi(s, 0, 16);
std::cout << "value in decimal = " << num << '\n';
std::cout << "value in hexadecimal = " << std::hex << num << '\n';
ss << "0x" << std::hex << num << '\n'; //
std::string res = ss.str();
std::cout << "result " << res << '\n';
}
#yogita, std::hex is just one of the configuration you need. You are probably missing the setfill and the setw configuration, as following:
#include <iostream>
#include <sstream>
#include <iomanip>
int main()
{
std::stringstream ss;
std::string s = "0x06A4";
int num = std::stoi(s, nullptr, 16);
std::cout << "value in decimal = " << num << '\n';
std::cout << "value in hexadecimal = " << std::hex << num << '\n';
ss << "0x" << std::hex << std::setfill('0') << std::setw(4) <<num << '\n';
std::string res = ss.str();
std::cout << "result " << res << '\n';
return 0;
}

Converting hex string to negative double

I'm trying to convert hex strings to double values, where some of the values are negative. This answer works fine for positive double hex strings, but when the double is negative I get a std::out_of_range exception. Why is that? Is there a way to get around it?
I have also tried to do the same thing with stringstream, and that works just fine for both positive and negative hex strings. So there is always that solution, but to me the union approach looks a bit more elegant. A matter of taste I guess.
Sample code:
#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
int main()
{
std::string str1("3fb999999999999a"); // 0.1
std::string str2("bfb999999999999a"); // -0.1
// ******************************
// UNION
// ******************************
union uint64double
{
unsigned long long i;
double d;
};
uint64double val1;
val1.i = std::stoll(str1, nullptr, 16);
uint64double val2;
val2.i = std::stoll(str2, nullptr, 16); // This throws std::out_of_range exception
const int w = 18;
std::cout << "USING UNION" << std::endl;
std::cout << std::setw(w) << "HEX" << std::setw(w) << "DOUBLE" << std::endl;
std::cout << std::setw(w) << str1 << std::setw(w) << val1.d << std::endl;
std::cout << std::setw(w) << str2 << std::setw(w) << val2.d << std::endl;
std::cout << std::endl;
// ******************************
// STRINGSTREAM
// ******************************
unsigned long long i1;
std::stringstream ss;
ss << std::hex << str1;
ss >> i1;
double d1(reinterpret_cast<double&>(i1));
unsigned long long i2;
ss.clear();
ss << std::hex << str2;
ss >> i2;
double d2(reinterpret_cast<double&>(i2));
std::cout << "USING STRINGSTREAM" << std::endl;
std::cout << std::setw(w) << "HEX" << std::setw(w) << "DOUBLE" << std::endl;
std::cout << std::setw(w) << str1 << std::setw(w) << d1 << std::endl;
std::cout << std::setw(w) << str2 << std::setw(w) << d2 << std::endl;
std::cout << std::endl;
return 0;
}
Output:
USING UNION
HEX DOUBLE
3fb999999999999a 0.1
bfb999999999999a 1.#QNAN
USING STRINGSTREAM
HEX DOUBLE
3fb999999999999a 0.1
bfb999999999999a -0.1
I'm using VS2012
Of course stoll throws std::out_of_range exception on input "bfb999999999999a", because 0xbfb999999999999a > LLONG_MAX. If you use stoull instead, everything works nicely, because 0xbfb999999999999a <= ULLONG_MAX.
You can pass the hex string into the stringstream constructor to clean it up a bit. Your std::hex is in the wrong place. std::hex tells the stream to treat the input as a hex value, rather than just a bunch of characters.
I would put this functionality in its own function too, to make it cleaner:
#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
double hexToDouble(const std::string& hex)
{
double d = 0;
std::stringstream ss(hex);
ss >> std::hex >> reinterpret_cast<uint64_t&>(d); // I feel dirty
return d;
}
int main()
{
std::string str1("3fb999999999999a"); // 0.1
std::string str2("bfb999999999999a"); // -0.1
std::cout << str1 << ' ' << hexToDouble(str1) << std::endl;
std::cout << str2 << ' ' << hexToDouble(str2) << std::endl;
return 0;
}

Can you create a string in a similar fashion to std::cout?

The following statement pipes all sorts of output to the console as a single string of text
std::cout << "Hi, my name is " << name_as_string << " and I am " << age_as_int << " years old, while weighing " << weight_as_double << " kilograms.";
Can we use this same syntax to build a string in a string variable? How is it done?
#include <sstream>
std::ostringstream ss;
ss << "Hi, my name is " << name_as_string;
ss << " and I am " << age_as_int << " years old, while weighing ";
ss << weight_as_double << " kilograms.";
std::string str = ss.str();
You can also use std::istringstream for multiple input, and std::stringstream for both input and output.
std::string str = "1 2 3 4 5";
std::istringstream ss(str);
int i;
while( ss >> i) {
std::cout << i;
}
stringstream will rescue you here;
#include <sstream>
std::stringstream ss;
ss << stuff << to << output;
std::string s = ss.str();
Use std::ostringstream
By using std::stringstream :
#include <sstream>
#include <iostream>
int main()
{
std::stringstream ss;
ss << "Hi, my name is " << name_as_string << " and I am " << age_as_int << " years old, while weighing " << weight_as_double << " kilograms.";
std::cout<<ss.str()<<std::endl;
}