C MongoDB driver DateTime update - c

Ok this is the scenario. I am reading txt file and inserting/updating (with bulk operations ) data to mongodb.
Inserting part works fine since I am creating bson document in a loop and doing mongoc_bulk_operation_insert.
My date comes in a format of 11:37:17.253 SAST JUN 05 2015
so I run it trough the function that removes .253 and SAST
and feed it to the convert_to_date function that you see down in the text.
This is how I create timestamp and append the date to the document:
int convert_to_date(char *dateString)
{
struct tm *parsedTime;
time_t rawTime;
time_t newTime;
int hour, minutes, seconds, millis, year, month, day;
if (sscanf(dateString, "%d:%d:%d %d %d %d",
&hour, &minutes, &seconds, &month, &day, &year) != EOF) {
time(&rawTime);
parsedTime = localtime(&rawTime);
parsedTime->tm_year = year - 1900;
parsedTime->tm_mon = month - 1;
parsedTime->tm_mday = day;
parsedTime->tm_hour = hour;
parsedTime->tm_min = minutes;
parsedTime->tm_sec = seconds;
newTime = mktime(parsedTime);
return newTime;
}
return 0;
}
/* this is somewhere in a loop */
time_t t = convert_to_date(s1);
bson_append_time_t(doc, field_map[y], strlen(field_map[y]), t);
// and after all if insert is supposed to happen i call
// mongoc_bulk_operation_insert(bulk, doc);
// and mongoc_bulk_operation_execute(bulk, &reply, &error);
That part is just fine when I look at the database I get
ISODate("2015-06-05T09:37:17.000Z")
So ther problem is when I try to update existing record.
When i do update i need to do a $set on all of the fields I want to update(upsert actually and I didnt find a way to update complete document at once)
it looks like this:
//update document with sessionid
query = BCON_NEW("SessionId", BCON_UTF8(sid));
update = BCON_NEW("$set", "{", "SomeDateTimeField",
BCON_DATE_TIME(ystack[y]), "}");
mongoc_bulk_operation_update(bulk, query, update, true);
The value of ystack[y] is 1433497048 which is valid timestamp but
i get in the db ISODate("1970-01-17T14:11:37.037Z")
I also found an example online for inserting the whole bson object as date like this:
int64_t currentTime = time(NULL) * 1000;
bson_t *date = BCON_NEW("$date", BCON_DATE_TIME(currentTime));
bson_t *update = BCON_NEW("$set", "{", "last_sync_time", date, "}");
But this produces \u0001 in the DB instead of valid date. I cant tell what is causing this, so much frustration for something that should be straight forward. This is the libbson api for the reference
https://api.mongodb.org/libbson/current/index.html
and c driver api
http://api.mongodb.org/c/1.1.8/

Ok I found the solution myself, should have read the api more carefully :)
The BCON_DATE_TIME accepts milliseconds instead of seconds which I passed to it.
I actually tried to multiply by 1000 before but since my var was int it could not store the correct value.
I had to declare it as
unsigned long long
Here is the changed code just for reference
long convert_to_long(char *dateString)
{
struct tm *parsedTime;
time_t rawTime;
time_t newTime;
int hour, minutes, seconds, millis, year, month, day;
if (sscanf(dateString, "%d:%d:%d %d %d %d",
&hour, &minutes, &seconds, &month, &day, &year) != EOF) {
time(&rawTime);
parsedTime = localtime(&rawTime);
parsedTime->tm_year = year - 1900;
parsedTime->tm_mon = month - 1;
parsedTime->tm_mday = day;
parsedTime->tm_hour = hour;
parsedTime->tm_min = minutes;
parsedTime->tm_sec = seconds;
newTime = mktime(parsedTime);
unsigned long long millis = newTime * 1000;
return millis;
}
return 0;
}

Related

How to get current day of month properly in Tizen c program

the following program works with c compiler and returns correct date. But on tizen app code it returns 0:
time_t my_time;
struct tm * timeinfo;
time (&my_time);
timeinfo = localtime (&my_time);
int y = timeinfo->tm_year+1900;
int m = timeinfo->tm_mon+1;
int d = timeinfo->tm_mday;
char day[10];
dlog_print(DLOG_DEBUG, "GG", "Current time: %d %d %d", y,m,d);
required screenshot:
it shows 0 only for date(d) but other m and y is printed correctly. Also similar code prints correct date on other c complier program.
How to get current day of the month properly?
You can use Watch Application API on the wearable profile.
You can also find sample code in Tizen Studio sample application(Classic Watch) like as below.
/**
* #brief Called at each second. This callback is not called while the app is paused or the device is in ambient mode.
* #param[in] watch_time The watch time handle. watch_time will not be available after returning this callback. It will be freed by the framework.
* #param[in] user_data The user data to be passed to the callback functions
*/
void app_time_tick(watch_time_h watch_time, void* user_data)
{
int hour = 0;
int min = 0;
int sec = 0;
int year = 0;
int month = 0;
int day = 0;
int day_of_week = 0;
watch_time_get_hour(watch_time, &hour);
watch_time_get_minute(watch_time, &min);
watch_time_get_second(watch_time, &sec);
watch_time_get_day(watch_time, &day);
watch_time_get_month(watch_time, &month);
watch_time_get_year(watch_time, &year);
watch_time_get_day_of_week(watch_time, &day_of_week);
_set_time(hour, min, sec);
_set_date(day, month, day_of_week);
_set_moonphase(day, month, year);
}

time.h - struct tm and milliseconds

I have log data ranging from 1000 to 100000 entries all from different sources. The objective is to sort this data by time (quickly). I was prototyping in C and i'm stuck because it looks like tm doesn't support milliseconds. Am i missing something here ? Any suggestions ?
Idea:
Open file. Parse line-by-line and tokenize fields to c struct via strtok
1.1 Convert Date & Time to "struct tm".
1.2 Build linked list
Sort linked list based on time (don't know which sort algorithm i'd use)
Output
[Example]
YYYY-MM-DD,HH:MM:SS:MS , PID, TID , COMPONENT, Message
2017-03-29,20:56:27:088, 3436,2568,COMPONENT, Message String blah blah
2017-03-29,20:56:27:089, 3436,2568,COMPONENT, Message String baaaaa
2017-03-29,20:56:27:079, 3436,2568,COMPONENT, Message String roarrr
2017-03-29,20:56:28:061, 3436,2568,COMPONENT, Message String meow
2017-03-29,20:56:25:044, 3436,2568,COMPONENT, Message String ruff ruff
.
.
.
100000 entries
const char T[] = "2017-03-29,20:56:27:088"; //Test String
time_t result = 0;
int year = 0, month = 0, day = 0;
int hour = 0, min = 0, sec = 0, ms = 0;
if (sscanf(T, "%4d-%2d-%2d,%2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec) == 6) {
struct tm tv = {0};
tv.tm_year = year;
tv.tm_mon = month;
tv.tm_mday = day;
tv.tm_hour = hour;
tv.tm_min = min;
tv.tm_sec = sec;
//Crap, it doesn't look like tm handles milliseconds ????
if ((result = mktime(&tv)) == (time_t)-1) {
fprintf(stderr, "Conversion Error\n");
}
puts(ctime(&result));
}
else {
fprintf(stderr, "Invalid Format\n");
}
I don't understand why you need to convert those timestamps into a struct tm, or into any other representation. They will already lexicographically sort just the way you want, in their current string form. So just do that.
You can take the result you get back from mktime and convert it to milliseconds.
if ((result = mktime(&tv)) == (time_t)-1) {
fprintf(stderr, "Conversion Error\n");
}
long long resultmilli = (result * 1000LL) + ms;

C Get Date Sometimes Wrong By 1 Day

So finally after a lot of time googling I've been able to create a function that gets current date and convert it to string then write to buffer in C. But I noticed sometimes the day is off by 1? So for example today is may 4, but it may return may 5
Here is my code
void getCurrentDateTime(char * buffer)
{
time_t t = time(NULL);
struct tm *tm = localtime(&t);
char bufForOut[64] = { 0 };
strftime(bufForOut, sizeof(bufForOut), "%c", tm);
strcpy(buffer,bufForOut);
}
I call it like
char hi[64] = { 0 }
getCurrentDateTime(hi);
print(hi);

Convert a human readable Date to a GMT date

I have a human readable date which is in local time. I need to convert this human readable time to a GMT time in a human readable form.
The human readable date I have is 30th March 2014 02:59.
When I convert the time to GMT I'm expecting the time to be 01:59 on the 30th but my conversion still comes out as 2:59.
I believe the only way to do the conversion is to convert the human time to an epoch and then convert this back to gmtime but doing this I still get 2:59.
Below is the code I am using:
struct tm t;
struct tm *gmtTimeStruct;
time_t t_of_day;
int year = atoi(date);
int month = atoi(date+5);
int day = atoi(date+8);
int hour = atoi(time);
int minutes = atoi(time+3);
char * gmtHumanTime = NULL;
printf("Year: %i Month: %i Day: %i Hour: %i Minutes: %i\n", year, month, day, hour, minutes);
t.tm_year = year - 1900;
t.tm_mon = month - 1;
t.tm_mday = day;
t.tm_hour = hour;
t.tm_min = minutes;
t.tm_sec = 59;
t.tm_isdst = 0;
t_of_day = mktime(&t);
printf("Epoch time: %ld\n", t_of_day);
gmtTimeStruct = gmtime(&t_of_day);
asprintf(&gmtHumanTime, "%s:%s", gmtTimeStruct->tm_hour, gmtTimeStruct->tm_min);
printf("GMT Human Time: %s", gmtHumanTime);
UPDATE 1
I've also tried change the t.tm_isdst flag from 0,1 and -1 to see if anything changes and it doesn't seem to. I know mktime has an issue with this flag as it can't always work out whether the time needs ammending due to DST or not but I'm not sure if timegm has the same issue.
Here's your problem:
The Daylight Saving Time flag (tm_isdst) is greater than zero if Daylight Saving Time is in effect, zero if Daylight Saving Time is not in effect, and less than zero if the information is not available.
By setting t.tm_isdst = 0; in your code, you are explicitly specifying that there is no daylight saving in effect. You should have provided a negative value.
Reference: http://www.cplusplus.com/reference/ctime/tm/
(Also, shouldn't the format string near the bottom be "%d:%02d"instead of "%s:%s"?)
EDIT
Sorry, I didn't notice you'd tried different values of tm_isdst. Perhaps it would help if you simplified your code a bit. This works perfectly on my system:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
struct tm t, *gmtTimeStruct, *localTimeStruct;
time_t t_of_day;
char *gmtHumanTime, *localHumanTime;
t.tm_year = 2014 - 1900;
t.tm_mon = 3 - 1;
t.tm_mday = 30;
t.tm_hour = 2;
t.tm_min = 59;
t.tm_sec = 59;
t.tm_isdst = -1;
t_of_day = mktime(&t);
gmtTimeStruct = gmtime(&t_of_day);
asprintf(&gmtHumanTime, "%d:%d", gmtTimeStruct->tm_hour, gmtTimeStruct->tm_min);
printf("GMT Human Time: %s\n", gmtHumanTime);
localTimeStruct = localtime(&t_of_day);
asprintf(&localHumanTime, "%d:%d", localTimeStruct->tm_hour, localTimeStruct->tm_min);
printf("Local Human Time: %s\n", localHumanTime);
return 0;
}
Output:
GMT Human Time: 1:59
Local Human Time: 2:59
Try compiling this on your system and see what you get. (Perhaps there is something wrong with your system's time zone setting?)

Convert struct array to struct?

I have a struct array (Training data[10]) that contains some data that I want to pass to functions.
int convertTime(Time time)
{
minutes = time.seconds * 60;
// Takes data from data[0].time.seconds and converts them to minutes.
// My only problem is that I am being asked send a struct to this function, but I have to send the array because that's where all my data is stored
return minutes;
}
typedef struct
{
int seconds;
} Time;
typedef struct
{
Time time;
double distance;
} Training;
Training data[10];
Training input;
scanf("%d %lf", input.time.seconds, input.distance);
data[0].time.seconds = input.time.seconds;
data[0].distance = input.distance;
So now data[0].time.seconds and data[0].distance contains all data I need. I just have to pass data[0].time.seconds to the function, but in my assignment I am prompted to send the struct Time to the function, and I don't understand that since Time is only storing temporary data? It's the stored data that I want to send to the function.
How do I convert seconds to hours, minutes and seconds?
time.hours = seconds / 3600;
time.minutes = (seconds - time.hours * 3600) / 60;
time.seconds = seconds - 3600 * time.hours - 60 * time.minutes;
This seems to be right in my eyes but it fails. hours is correctly calculated but not minutes and sconds :(
To pass the structure, name it in the call:
some_function(data[0].time); // By value
other_function(&data[0].time); // By address
Both functions get passed the Time value contained in the data[0] element of your array of Training structures.
Suppose you have a value which is the number of seconds since midnight. And suppose you define another structure with hours/minutes/seconds, you can set this clock structure as follows,
typedef struct
{
int hours;
int minutes;
int seconds;
} Clock;
You can print this structure, either to a char buffer, or to stdout,
char*
clockPrint(Clock* timep,char *stringbuf)
{
if(stringbuf)
sprintf(stringbuf,"%02d:%02d:%02d",(timep)->seconds,(timep)->minutes,(timep)->seconds);
else
printf("%02d:%02d:%02d",(timep)->seconds,(timep)->minutes,(timep)->seconds);
return stringbuf;
}
Extracting hours, minutes, and seconds from an epoch time or a number of seconds since midnight can be done,
int //return days...
TimeSet(Clock* timep, int epoch)
{
(timep)->seconds = (epoch) % 60;
(timep)->minutes = (epoch/60) % 60;
(timep)->hours = (epoch/60/60) % 24;
int days;
return days = (epoch/60/60/24);
}
Should you want to obtain hours, minutes, or seconds from this clock value,
void
TimeGet(Clock* timep, int* hoursp, int* minutesp, int* secondsp)
{
if(hoursp) *hoursp = (timep)->hours;
if(minutesp) *minutesp = (timep)->minutes;
if(secondsp) *secondsp = (timep)->seconds;
return;
}
Since you have stored a Time in your Date struct, which contains a number of seconds (presumably since midnight), and you have an array of some number of these Date's defined,
Training data[10];
Training input;
You can use scanf to read your seconds and distance values. And as stated, you can then place your input into your data[0] element,
//scanf wants pointers to int and float data
float distance;
printf("enter: seconds distance "); fflush(stdout);
scanf("%d %lf", &(input.time.seconds), &distance);
//you can then store the distance into your input struct double
input.distance = distance;
data[0].time.seconds = input.time.seconds;
data[0].distance = input.distance;
You could also use gettimeofday(3) or clock_gettime(2) to grab the current time (seconds since epoch),
struct timeval tv;
gettimeofday(&tv,NULL); //posix.1-2001 function, seconds
input.time.seconds = tv.tv_sec;
//or
struct timespec ts;
clock_gettime(CLOCK_REALTIME,&ts); //posix.1-2008 function, seconds
input.time.seconds = ts.tv_sec;
Then you can separate your seconds into hours, minutes, and seconds,
Clock clk;
int hours, minutes, seconds;
TimeSet(&clk, data[0].time.seconds);
TimeGet(&clk, &hours, &minutes, &seconds);
Or you can format a string for printing, or print to stdout,
char clockbuffer[30];
clockPrint(&clk,NULL);
printf("time (HH:MM:SS): %s\n", clockPrint(&clk,clockbuffer));

Resources