I'm trying to create a program that takes the difference of two military times and get its time difference.
Example:
**AM to PM**
Time 1: 0900
Time 2: 1730
Time Difference: 8 hours 30 minutes
**PM to AM**
Time 1: 1200
Time 2: 1100
Time Difference: 23 hours 0 minutes
Using a couple of if than else statements, I was able to figure out how to convert from military hours into standard hours but I'm stuck with how to go about subtracting time. I was trying to come up with a way to do with on paper just with addition and subtraction but I haven't developed a method that works in all cases. Any help?
One option might be to split the time into two elements, the hours and the minutes.
First, take the time, ie. 1730 and divide by 100. If its an integer or similar, it should result in 17 hours (it will automatically round down).
Then take 1730 and mod it by 100 to get 30 minutes.
int time1 = 900;
int time2 = 1730;
int diffHours = time2 / 100 - time1 / 100;
int diffMinutes = time2 % 100 - time1 % 100;
If you're unfamiliar with modulus (%), it just returns the remainder after dividing the two numbers, so 7 % 3 would be 1.
Assuming your military times are stored as int values in the range 0000..2400, then the following function will return the difference between two such values.
#include <cassert>
extern int timediff_minutes(int t1, int t2);
int timediff_minutes(int t1, int t2)
{
assert(t1 >= 0 && t1 <= 2400);
assert(t2 >= 0 && t2 <= 2400);
assert(t1 % 100 < 60 && t2 % 100 < 60);
int t1_mins = (t1 / 100) * 60 + (t1 % 100);
int t2_mins = (t2 / 100) * 60 + (t2 % 100);
return(t2_mins - t1_mins);
}
Note that 2400 is useful for representing the end of the day — and using 2400 is sanctioned by ISO 8601:2004 Data elements and interchange formats — Information interchange — Representation of dates and times.
4.2.3 Midnight
The complete representations in basic and extended format for midnight, in accordance with 4.2.2, shall be
expressed in either of the two following ways:
Basic format Extended format
a) 000000 00:00:00 (the beginning of a calendar day)
b) 240000 24:00:00 (the end of a calendar day)
The representations may have reduced accuracy in accordance with 4.2.2.3 or may be designated as a time
expression in accordance with 4.2.2.5. To represent midnight the representations may be expanded with a
decimal fraction containing only zeros in accordance with 4.2.2.4.
NOTE 1 Midnight will normally be represented as [00:00] or [24:00].
NOTE 2 The end of one calendar day [24:00] coincides with [00:00] at the start of the next calendar day, e.g. [24:00] on
12 April 1985 is the same as [00:00] on 13 April 1985. If there is no association with a date or a time interval both a) and b)
represent the same local time in the 24-hour timekeeping system.
NOTE 3 The choice of representation a) or b) will depend upon any association with a date, or a time interval.
Representations where [hh] has the value [24] are only preferred to represent the end of a time interval in accordance with
4.4 or recurring time interval in accordance with 4.5.
Related
So I want to creata a time stamp (as a string) with the format HH:MM:SS in C++. I use std::chrono to get a unix time stamp and then calculate the hours, minutes and seconds.
// Get unix time stamp in seconds.
const auto unix_time_stamp = std::chrono::system_clock::now();
long long seconds_since_epoch = std::chrono::duration_cast<std::chrono::seconds>(unix_time_stamp.time_since_epoch()).count();
// Calculate current time (hours, minutes, seconds).
uint8_t hours = (seconds_since_epoch % 86400) / 3600;
uint8_t minutes = (seconds_since_epoch % 3600) / 60;
uint8_t seconds = (seconds_since_epoch % 60);
// Create strings for hours, minutes, seconds.
std::string hours_string = std::to_string(hours);
std::string minutes_string = std::to_string(minutes);
std::string seconds_string = std::to_string(seconds);
// Check if the number is only one digit. If it is, add a 0 in the beginning (5:3:9 --> 05:03:09).
if(hours_string.size() == 1)
{
hours_string = "0" + hours_string;
}
if(minutes_string.size() == 1)
{
minutes_string = "0" + minutes_string;
}
if(seconds_string.size() == 1)
{
seconds_string = "0" + seconds_string;
}
// Append to a final string.
std::string time_stamp = hours_string + ":" + minutes_string + ":" + seconds_string;
This is all working fine and great but there is one big problem: time zones.
With this way, I'm only calculating the time stamp for GMT. Is there any easy, fast and, most importantly, portable way to get the "offset" in seconds or minutes or hours for your system's time zone? By "portable" I mean platform-independent.
Please note: I know you can do all of this more easily with std::strftime and so on, but I really want to implement this by myself.
Some implementations of std::tm will contain a member that has the local offset as a member. ... But it isn't portable.
One trick is to take your seconds_since_epoch, and either assign it to a std::time_t, or just make its type std::time_t in the first place instead of long long.
... Oh, wait that isn't quite portable. Some platforms still use a 32 bit time_t. But assuming a 64 bit time_t ...
Then use localtime to get a std::tm:
std::tm tm = *localtime(&seconds_since_epoch);
This isn't officially portable because system_clock and time_t aren't guaranteed to have the same epoch. But in practice they do.
Now take the {year, month, day, hour, minute, second} fields out of the tm and compute a "local epoch". The hard part of this computation is converting the {year, month, day} part into a count of days. You can use days_from_civil from here to do that computation efficiently. Be sure to take the weird offsets into account for tm_year and tm_mon when doing this.
After you get this then subtract seconds_since_epoch from it:
auto offset = local_epoch - seconds_since_epoch;
This is your signed UTC offset in seconds. Positive is east of the prime meridian.
In C++20 this simplifies down to:
auto offset = std::chrono::current_zone()->get_info(system_clock::now()).offset;
and offset will have type std::chrono::seconds.
You can get a free, open-source preview of this here. It does require some installation.
I have a long int variable wich containes seconds since Jan. 1, 1970 in this format:
long int seconds = 1231241242144214;
i need to convert this seconds to double precision floating-point value. The integer part of the value is the number of days since midnight, 30 December 1899.
The fractional part of the value represents time. .5 is equal to 12:00 PM.
how can i convert?
There are 86400 seconds in a day, and 25569 days between these epochs. So the answer is:
double DelphiDateTime = (UnixTime / 86400.0) + 25569;
You really do need to store the Unix time in an integer variable though.
Suppose we have
#include <chrono>
#include <iostream>
#include <ctime>
namespace Ratios { typedef std::ratio<60*60*24,1> Days; }
typedef std::chrono::system_clock Clock;
typedef Clock::time_point TimePoint;
And our main looks like
int main(int argc, char *argv[])
{
// argc check left out for brevity
const Clock::rep d = static_cast<Clock::rep>(std::atoi(argv[1]));
// Right now
TimePoint now = Clock::now();
// Start with zero days
auto days = std::chrono::duration<Clock::rep, Ratios::Days>::zero();
// Now we'd like to add d to the days
days += d; // Error!
days.count() = d; // Error!
days = days + d; // Error!
days += std::chrono::duration<Clock::rep, Ratios::Days>(d); // Okay
days = days + std::chrono::duration<Clock::rep, Ratios::Days>(d); // Okay
days *= d; // Why is this okay?
days %= d; // And this too?
TimePoint later = now + days;
return 0;
}
What is the reason behind prohibiting the user to manipulate a duration directly?
It is done to enforce you to stick to strongly typed values rather than arbitrary values.
Bjarne Stroustrup has examples regarding this behaviour in "The C++ Programming Language" (4th Ed., 35.2.1, pp. 1011):
"The period is a unit system, so there is no = or += taking a plain value. Allowing that would be like allowing the addition of 5 of an unknown SI unit to a length in meters. Consider:
duration<long long, milli> d1{7}; // 7 milliseconds
d1 += 5; // error
[...]
What would 5 mean here? 5 seconds? 5 milliseconds? [...] If you know what you mean, be explicit about it. For example:
d1 += duration<long long, milli>{5}; //OK: milliseconds"
The rationale is to maintain the integrity of the unit of time which duration represents.
You can think of the rep as being unit-less. But the duration is has a unit of time. One can add and subtract seconds to/from seconds. But one can not add seconds and a unit-less quantity without making the expression ambiguous, and violating the algebra of units.
That being said, one can multiply and divide a unit of time by a scalar (a unit-less) quantity, and the result is still a unit of time. This library only represents units of time to the first power, or zero power. A unit of time raised to the zero power is a scalar and is represented by rep. Units of time can also have power of 2 or more, and negative powers. However this library does not represent such units.
When adding two quantities, the units must be the same.
When multiplying or dividing two quantities, a new unit is formed (e.g. km/hr). When quantities of the same units are multiplied, their exponents are added (e.g. sec * sec == sec^2). When quantities of the same units are divided, their exponents are subtracted (e.g. sec / sec == sec^0 == a scalar).
The std::chrono::duration library is a consistent subset of a physical quantities library that handles only units of time and only those units of time with exponents equal to 0 and 1.
days += d; // Error!
This is because the variable days is in units of 86,400 seconds and the variable d is unitless. The result of adding a quantity of one unit to a unitless scalar is not defined under standard dimensional analysis.
days *= d; // Why is this okay?
days %= d; // And this too?
Because multiplying and dividing quantities by unitless scalars is not meaningless. Multiplying 2 seconds by 2 results in 4 seconds.
Consider multiplying 2 seconds by 3 seconds; the result is a quantity 6 with the unit 'seconds squared'. Of course chrono::duration isn't a complete units library so you can't have units like time squared, but libraries like boost.units will support that.
I would assume that this is done to force you to consider what the units of the duration you want to add/subtract are. It also keeps you from making any assumptions about what units the clock ticks are in.
I am receiving from a data provider timestamps that follow this specification:
number of 100 nanoseconds since 1601
I am using boost::posix_time::ptime and I would like to convert the timestamps to posix time. Is there a simple way to do that ?
When did the switch from the Julian to Gregorian calendar occur for this system? Some countries switched before 1st January 1601; others didn't switch until much later. This will critically affect your calculation - by 11 days or so.
Since there are 107 units of 100 ns each in one second, you divide the starting number by 107 to produce the number of seconds since the reference time (the remainder is the fraction of a second). You then divide that by 86400 to give the number of days (the remainder is the time of day). Then you can compute the date from the number of days.
Since POSIX time uses 1970-01-01 00:00:00 as the reference, you may simply need to compute the correct number of seconds between 1601-01-01 00:00:00 and the POSIX epoch (as it is known), and subtract that number from the number of seconds you calculated.
number of 100 nanoseconds since 1601
It is Windows FILETIME value.
Boost.DateTime actually use Windows FILETIME for Windows platform.
Below is the relevant Boost source code that convert FILETIME to boost::posix_time::ptime:
(from boost/date_time/microsec_time_clock.hpp)
static time_type create_time(time_converter converter)
{
winapi::file_time ft;
winapi::get_system_time_as_file_time(ft);
uint64_t micros = winapi::file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
// and cannot be before 1970-Jan-01
std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch
// microseconds -- static casts supress warnings
boost::uint32_t sub_sec = static_cast<boost::uint32_t>(micros % 1000000UL);
std::tm curr;
std::tm* curr_ptr = converter(&t, &curr);
date_type d(curr_ptr->tm_year + 1900,
curr_ptr->tm_mon + 1,
curr_ptr->tm_mday);
//The following line will adjust the fractional second tick in terms
//of the current time system. For example, if the time system
//doesn't support fractional seconds then res_adjust returns 0
//and all the fractional seconds return 0.
int adjust = static_cast< int >(resolution_traits_type::res_adjust() / 1000000);
time_duration_type td(curr_ptr->tm_hour,
curr_ptr->tm_min,
curr_ptr->tm_sec,
sub_sec * adjust);
return time_type(d,td);
}
You can browse your Boost installation for the detailed implementation.
I'm trying to insert a timestamp (hour:min:sec) into a two-byte array and i'm a little confused on how to accomplish this...any help is greatly appreciated!
int Hour = CTime::GetCurrentTime().GetHour();
int Minute = CTime::GetCurrentTime().GetMinute();
int Second = CTime::GetCurrentTime().GetSecond();
BYTE arry[2];
//Need to insert 'Hour', 'Minute', & 'Second' into 'arry'
Thanks!
You can't. There are potentially 86402 seconds in a day (a day can have up to two leap seconds), but the 16 bits available to you in a byte[2] array can only represent 65536 separate values.
hour:min:sec is not what people call timestamp. A timestamp is the number of seconds elapsed since 1970-01-01 and will surely not fit into 16 bits.
Assuming ranges of hours=[0;24], minutes=[0;60], seconds=[0;60] (leap seconds included) you will need 5+6+6=17 bits which still won't fit into 16 bits.
If you had a 32-bit array, it would fit:
int Hour = CTime::GetCurrentTime().GetHour();
int Minute = CTime::GetCurrentTime().GetMinute();
int Second = CTime::GetCurrentTime().GetSecond();
uint8_t array[4];
// Just an example
*(uint32_t*)array = (Hour << 12) | (Minute << 6) | Second;
This sounds somewhat like homework for me... or what is the exact purpose of doing this?