User Typed Time in C++
Date and Time in C++ Simplified - Part 2
Forward: In this part of the series, we look at the situation where the user actually types the time into a C++ program as opposed to reading the time from the computer processor.
By: Chrysanthus Date Published: 25 Aug 2012
Introduction
C++ Standard Library
C++ installation comes with a library that has important and common features (ready-made code segments) that you can use, without writing code for the features. This library is called the standard library. The library is divided into categories. These categories are still called libraries. The categories are divided into components. Components are divided into entities. Entities are basic things like data types and functions.
There are many header files for the standard library. You access a feature (entity) through a header file. With a typical C++ installation, you do not need to know where (directory) the standard library or standard libraries are kept; you do not need to even know where the header files for the standard library are kept. With my installation (mingw), all you need to know is the name of the header files. To use the header files, you just need to include it at the top of your code (without indicating the path). You do that using the #include preprocessing directive with the name of the header file alone in angle brackets.
How do you know which feature is in a header file. One way to know that is by reading articles, which are of reference nature like this one (series).
What I give you in this series is a simplified version of what is in the ISO/IEC 14882:2003 C++ specification.
Prerequisite
There are other articles (tutorials) I have written in this blog on C++. You need to have read them or articles similar to them before reading this series. The titles of the articles or series in this blog, which are prerequisite to reading this series are:
- Getting Started with C++
- Integer and Float Object Types in C++
- Assignment Operators in C++
- User Types from Fundamental Types in C++
A computer language builds up. There are certain things you have to learn first and then use them to learn higher things. Each of the above titles is either a tutorial or the first tutorial in a series. If it is the first part of a series, then you should have read the whole series. If it is a tutorial standing alone, then you should have read the tutorial. To reach any of the articles, just type the title of the article and my name Chrys in the Search Box of this page and click Search.
The header file that has the time features is called, ctime.
The struct tm Object Data
The ctime header has an object type (Data type) called, struct tm. You type “struct” then a space and then “tm”. This is a special kind of struct and you use it in the same way that you use other structs.
An example of time is, “Sun Sep 16 01:03:52 1973”. This time can be broken down to week-day (Sun), month (Sep), month day (16), hour (01), etc. When time is given in the form of its individual items it is said to be Broken Down Time. The struct tm object is used to hold the broken down time. A summary of the descriptions of the identifiers in the struct is as follows:
int tm_sec; // seconds after the minute — [0, 59]
int tm_min; // minutes after the hour — [0, 59]
int tm_hour; // hours since midnight — [0, 23]
int tm_mday; // day of the month — [1, 31]
int tm_mon; // months since January — [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday — [0, 6]
int tm_yday; // days since January 1 — [0, 365]
int tm_isdst; // Daylight Saving Time flag
You have to use these identifiers in your code as given. All the identifiers identify struct internal objects of type int. Read through the summary to appreciate the values of the identifiers and their ranges. Each value is an integer. For example, day of the month is not January, February, March, etc. Rather it is 1, 2, 3, etc. In your code, the order in which you assign ints to the identifiers does not matter; just make sure you respect the range.
There are a few other things to note about the ranges. The year you consider has to be a four-digit year beginning from 1900 and upward. Note: in the summary the value for tm_year is an int not the for-digit year; it is an int resulting from the difference of the four-digit year from 1900.
In the following code, the items of the time, “Sun Sep 16 01:03:52 1973” are assigned to the identifiers of a struct tm object. Read and try it.
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
struct tm timeBroken;
timeBroken.tm_sec = 52;
timeBroken.tm_min = 03;
timeBroken.tm_hour = 01;
timeBroken.tm_mday = 16;
timeBroken.tm_mon = 9;
timeBroken.tm_year = 1973 - 1900;
timeBroken.tm_wday = 0;
timeBroken.tm_isdst = 0;
cout << timeBroken.tm_wday << '\n';
cout << timeBroken.tm_mon << '\n';
cout << timeBroken.tm_mday << '\n';
cout << timeBroken.tm_hour << '\n';
cout << timeBroken.tm_min << '\n';
cout << timeBroken.tm_sec << '\n';
cout << timeBroken.tm_year << '\n';
return 0;
}
In the code, timeBroken is the name given to the special object of type, struct tm. Note how the year (tm_year) value was determined. You have to subtract the year of interest from 1900 as in (1973 - 1900). Also note that I did not type in “Sun” and “Sep” for the week-day and month; I typed in numbers (integers).
From the above code, the way (one item per line) the time has been printed is not very convenient. Would it not be nice for the code to print it back as “Sun Sep 16 01:03:52 1973” (in that order as a string)?
In C++ time is held in the form of a struct tm object or another object called, time_t (time_t is also in the ctime header like other time entities). There are two functions for each of these objects that would convert each into a string. To covert the struct tm object into a string, the asctime function is used. The syntax is:
char *asctime(const struct tm *timeptr);
The argument is a pointer to a struct tm object and not the identifier of the object itself. So you have to create a pointer to the struct tm before using it in the argument. The return value is a pointer to a string of the time in struct tm. The string is a series of characters ending with n and . n enables the next output to go into the next line, while also included in the series at the end, tells C++ that the series is a string. The returned pointer actually points to the first character of the series of chars. The following code illustrates the use of the asctime function (read and try it).
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
struct tm timeBroken;
timeBroken.tm_sec = 52;
timeBroken.tm_min = 03;
timeBroken.tm_hour = 01;
timeBroken.tm_mday = 16;
timeBroken.tm_mon = 9;
timeBroken.tm_year = 1973 - 1900;
timeBroken.tm_wday = 0;
timeBroken.tm_isdst = 0;
struct tm *timeBrokenPtr = &timeBroken;
char *strPtr = asctime(timeBrokenPtr);
cout << strPtr;
return 0;
}
In this code, the tm_wday value is obligatory (should be typed) for the struct tm object because of asctime, but the tm_yday is not obligatory.
C++ time can be held in either a struct tm object or a time_t object. The nature of the time_t object depends on the manufacturer of the compiler (supplier); you do not have to know the nature. Time functions (in the ctime header), use the time_t object more than the struct tm object.
The mktime function converts time from struct tm to time_t. The syntax is,
time_t mktime(struct tm *timeptr);
It takes a pointer to a struct tm object as argument and not the identifier of the struct tm object. So in your code, you have to obtain the pointer before you can use it as argument in this function. You do not need to know the nature of the returned time_t object as each compiler manufacturer (supplier) has its own form. However, you need to know how to use the object (see below).
Some good news: if the values for tm_wday and tm_yday are not available in the struct tm object, the mktime function determines them and makes them available in the returned time_t object.
If some of the values in your struct tm object are not correct, the mktime function makes some adjustments to the values; the result may not always be what you expected.
Converting a time_t object to a String
The ctime function converts a time_t object to a string. The syntax is:
char *ctime(const time_t *timer);
timer is a pointer to a time_t object. So create the pointer first (if you do not have it) before you use it as argument in the ctime function. The return is the same as for the asctime function. By using the time_t pointer as argument in the ctime function, you are using the time_t object without knowing its nature.
Read and try the following code that illustrates the use of the mktime and ctime functions.
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
struct tm timeBroken;
timeBroken.tm_sec = 52;
timeBroken.tm_min = 03;
timeBroken.tm_hour = 01;
timeBroken.tm_mday = 16;
timeBroken.tm_mon = 9;
timeBroken.tm_year = 1973 - 1900;
timeBroken.tm_isdst = 0;
struct tm *timeBrokenPtr = &timeBroken;
time_t timeTObj = mktime(timeBrokenPtr);
time_t *timeTObjPtr = &timeTObj;
char *strPtr = ctime(timeTObjPtr);
cout << strPtr;
return 0;
}
Note that the values for tm_wday and tm_yday are not in the struct tm object but they are in the output since mktime determined and added them into the returned time_t object.
Note: the asctime and ctime functions return the week-day and month in three letter words, even though the struct tm object takes integers for those values.
You can use the gmtime function to convert a time_t object to a struct tm object. The syntax of the gmtime function is,
struct tm *gmtime(const time_t *timer);
The argument to the gmtime function is a pointer to a time_t object. The function returns a pointer to the returned, struct tm object. The following code illustrates the use of the function:
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
struct tm timeBrokenObj;
int yearFrom1900 = 1973 - 1900;
timeBrokenObj.tm_sec = 52;
timeBrokenObj.tm_min = 3;
timeBrokenObj.tm_hour = 1;
timeBrokenObj.tm_mday = 16;
timeBrokenObj.tm_mon = 9;
timeBrokenObj.tm_year = yearFrom1900;
timeBrokenObj.tm_wday = 0;
timeBrokenObj.tm_isdst = 0;
struct tm *timeBrokenObjPtr = &timeBrokenObj;
time_t timeTObj = mktime(timeBrokenObjPtr);
time_t *timeTObjPtr = &timeTObj;
struct tm *newVersionTimeBroken = gmtime(timeTObjPtr);
cout << (*newVersionTimeBroken).tm_wday << '\n';
cout << (*newVersionTimeBroken).tm_mon << '\n';
cout << (*newVersionTimeBroken).tm_mday << '\n';
cout << (*newVersionTimeBroken).tm_hour << '\n';
cout << (*newVersionTimeBroken).tm_min << '\n';
cout << (*newVersionTimeBroken).tm_sec << '\n';
cout << (*newVersionTimeBroken).tm_year << '\n';
return 0;
}
Note that the year returned in this code is the difference between the four-digit year in the time object and 1900.
Converting struct tm to time_t
To convert struct tm to time_t, use the mktime function.
Local Time and GMT Time
Another name for Greenwich Mean Time (GMT) is Coordinated Universal Time (UTC). It is the responsibility of you the coder to know if the time you are typing into the struct tm object is local or GMT time.
Difference Between Two Times
You can find the difference between two times in seconds. The function and syntax is:
double difftime(time_t time1, time_t time0);
The return value is a double, in seconds. The arguments are two values of type, time_t; so any struct tm should be converted to time_t.
Wow, we have seen some interesting things. Because we have seen a lot we can now take a break and continue in the next part of the series.
Chrys
Related Courses
C++ CourseRelational Database and Sybase
Windows User Interface
Computer Programmer – A Jack of all Trade – Poem
NEXT