Solved

Getting GMT time into a CTime

Posted on 2001-06-29
5
1,434 Views
Last Modified: 2013-11-20
When our server passes time/date values to clients, it does so in a formatted string representing the time in GMT (UTC).  It's easy to get UTC from a CTime object with FormatGmt(), but there does not seem to be a way to put UTC back into another CTime object after we parse that string.  Any time that I give to CTime seems to be interpreted as local time.

A clumbsy workaround is to store the original values of _timezone and _daylight (global variables in C runtime), set them to 0, construct my CTime object, then restore the variables.  This works, but is ugly and obviously not threadsafe.

Can anyone offer a better alternative?

In short, I'm looking for a function like:

CTime GetCTimeFromGmt(int year, int month, int day, int hour, int minute, int second)
{
}

where the passed parameters are relative to GMT.  The function must be thread safe.

Thanks,
Matthew
0
Comment
Question by:azami
  • 3
  • 2
5 Comments
 
LVL 12

Accepted Solution

by:
migel earned 100 total points
Comment Utility
Hi!
you can use another constructor of the CTime that uses time_t values

main ide since CTime constructor uses mktime CRT function
calc time_t value two times. The first as local time(mktime) and the second as global time. The difference between these times (by difftime) is the our timezone.
So adjust our time to this value.

CTime GetCTimeFromGmt(int year, int month, int day, int hour, int minute, int second)
{
     struct tm atm;
     atm.tm_sec = nSec;
     atm.tm_min = nMin;
     atm.tm_hour = nHour;
     ASSERT(nDay >= 1 && nDay <= 31);
     atm.tm_mday = nDay;
     ASSERT(nMonth >= 1 && nMonth <= 12);
     atm.tm_mon = nMonth - 1;        // tm_mon is 0 based
     ASSERT(nYear >= 1900);
     atm.tm_year = nYear - 1900;     // tm_year is 1900 based
     atm.tm_isdst = -1; //DST is unknown
     time_t tm_t = mktime(&atm);
// now calculate this time_t as UTC
struct tm *newtime;
newtime = gmtime( &tm_t );
// timezone can be calculated as newtime.tm_hour-hour
// also check possible date changing
atm.tm_hour += atm.tm_hour -newtime.hour;
tm_t = mktime(&atm);
return CTime(tm_t);
}
0
 
LVL 1

Author Comment

by:azami
Comment Utility
The ripple effect when we cross a day boundary (need to see if the day is right, and the month, and the year...)  Seems a bit much.  But this seems to work:

CTime GetCTimeFromGmt(int year, int month, int day, int hour, int minute, int second)
{
     struct tm gmt_struct;
     gmt_struct.tm_sec = second;
     gmt_struct.tm_min = minute;
     gmt_struct.tm_hour = hour;
     ASSERT(day >= 1 && day <= 31);
     gmt_struct.tm_mday = day;
     ASSERT(month >= 1 && month <= 12);
     gmt_struct.tm_mon = month - 1;        // tm_mon is 0 based
     ASSERT(year >= 1900);
     gmt_struct.tm_year = year - 1900;     // tm_year is 1900 based
     gmt_struct.tm_isdst = -1; //DST is unknown
     
     time_t gmt_tt = mktime(&gmt_struct);
     
     // convert to gmt as though it was local time to get the offset
     struct tm *reversed_offset_struct = gmtime( &gmt_tt );
     time_t reversed_offset_tt = mktime(reversed_offset_struct);

     time_t offset = reversed_offset_tt - gmt_tt;

     time_t local_tt = gmt_tt - offset;

     return CTime(local_tt);
}

My only concern now is the thread safety of gmtime(), which uses a static buffer.  I think the MT CRT solves this, but I haven't been able to confirm one way or another.

I have to admit that I'm a bit surprised that neither CTime nor the C runtime offer a way to use GMT time as input!

Thanks for your help Migel.  I want to give this a few days to see whether anyone can comment on the thread safety before I accept your answer.

-Matthew
0
 
LVL 1

Author Comment

by:azami
Comment Utility
The ripple effect when we cross a day boundary (need to see if the day is right, and the month, and the year...)  Seems a bit much.  But this seems to work:

CTime GetCTimeFromGmt(int year, int month, int day, int hour, int minute, int second)
{
     struct tm gmt_struct;
     gmt_struct.tm_sec = second;
     gmt_struct.tm_min = minute;
     gmt_struct.tm_hour = hour;
     ASSERT(day >= 1 && day <= 31);
     gmt_struct.tm_mday = day;
     ASSERT(month >= 1 && month <= 12);
     gmt_struct.tm_mon = month - 1;        // tm_mon is 0 based
     ASSERT(year >= 1900);
     gmt_struct.tm_year = year - 1900;     // tm_year is 1900 based
     gmt_struct.tm_isdst = -1; //DST is unknown
     
     time_t gmt_tt = mktime(&gmt_struct);
     
     // convert to gmt as though it was local time to get the offset
     struct tm *reversed_offset_struct = gmtime( &gmt_tt );
     time_t reversed_offset_tt = mktime(reversed_offset_struct);

     time_t offset = reversed_offset_tt - gmt_tt;

     time_t local_tt = gmt_tt - offset;

     return CTime(local_tt);
}

My only concern now is the thread safety of gmtime(), which uses a static buffer.  I think the MT CRT solves this, but I haven't been able to confirm one way or another.

I have to admit that I'm a bit surprised that neither CTime nor the C runtime offer a way to use GMT time as input!

Thanks for your help Migel.  I want to give this a few days to see whether anyone can comment on the thread safety before I accept your answer.

-Matthew
0
 
LVL 12

Expert Comment

by:migel
Comment Utility
Hi!
IMHO all CRT routimes must be thread safe!
look at CRT source gmtime.c (...\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\) and you founs that it isn`t exception from mainstream :-)
0
 
LVL 1

Author Comment

by:azami
Comment Utility
I finally got around to installing the CRT source code to check.  I agree that the CRT _should_ be thread-safe, but unfortunately, not all of it is.  Fortunately, gmtime's buffer _is_ threadsafe, so the code (with my modifications) should work until the Y2.038K bug strikes.  BTW, _timezone and _daylight are among the globals that do not seem to have the thread-safety harness, so my original code that temporarily changed those (see question) was NOT threadsafe.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
How to create frequencies of a variable from SAS dataset? 10 115
Generic progress indicator 6 109
notReplace  challenge 53 102
no14 challenge 14 56
This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now