I have the following doubt on the usage of tm_isdst flag in the tm structure. As per man pages and googled results, I understand that its value is interpreted as follows
A. A value of 0 indicates DST is not in effect for the represented time
B. A value of 1 indicates DST is in effect
C. A value of -1 causes mktime to check whether DST is in effect or not.
It is this third point which is confusing me. My doubt is how mktime can figure out whether DST has to be applied or not accurately.
For example
My Time Zone = GMT + 3:00
DST shifting = +1 Hour at 5:00 AM in January (to keep it simple)
Current UTC time = "01/Jan/2012 00:00:00"
UTC time in seconds time_t timetUTC = X seconds
Hence my time is = "01/Jan/2012 03:00:00"
As time passes, my time value changes as follows
"01/Jan/2012 04:00:00" (X + 1 * 60 * 60)
"01/Jan/2012 05:00:00" (X + 2 * 60 * 60)
"01/Jan/2012 05:59:59" (X + 2 * 60 * 60 + 59)
"01/Jan/2012 05:00:00" (X + 3 * 60 * 60)
"01/Jan/2012 06:00:00" (X + 4 * 60 * 60)
As per my understanding
tm tmMyTime = localtime_r(X + 2 * 60 * 60) will set tmMyTime.tm_isdst to 0
tm tmMyTime = localtime_r(X + 3 * 60 * 60) will set tmMyTime.tm_isdst to 1
This way, even though all other components of tm structure are equal in both cases,
mktime(tmMyTime) can return proper UTC value, depending on tm_isdst value.
Now, if I set tmMyTime.tm_isdst = -1, what value would mktime return? I read about TZ variable, time database etc etc. In spite of all that, logically how can mktime() figure out whether to apply DST correction or not for those tm values that can occur twice?
We do not have DST in our time zone. Hence I am not very sure whether my understanding
is correct. Please correct me if I am wrong. Your help is much appreciated.
In short: it is implementation dependent.
mktime knows the DST rules by checking the locale.
For the bigger part of the year, mktime can figure out if DST is to be applied for a particular local time. The problem is indeed the "duplicate" hour when DST shifts backwards (in your example 05:00:00 - 05:59:59). For this local time range, given tm_isdst = -1, mktime cannot know if DST is in effect or not. Which one of these is chosen, differs from one implementation to another. With the GNU version of mktime, the UTC before the shift is returned.
tm_isdst cannot in general resolve ambiguous times. That's because many timezones have transitions (one-time) without jumping from dst to nodst, just changing offset and zone abbreviation. So both times (before and after transition) have the same tm_isdst.
Some other zones changes tm_isdst when switching summer/winter time but doesn't change abbreviation (Australia/Melbourne for example).
I think it's going to be somewhat dependent on your platform. In Windows, at least, the mktime() documentation states "The C run-time library assumes the United States’s rules for implementing the calculation of Daylight Saving Time", so it has a table of rules somewhere where it can determine when DST started / ended in any given year.
You're lucky not to have DST where you are. In my world, which is real-time data acquisition and presentation, DST is a big nuisance!
Related
I have a large data set with timestamps that are in UTC time in milliseconds. I'm synchronizing this data set with another's who has timestamps of microseconds past the hour, so I need to convert the first to local time, in seconds past the hour.
Most of the similar questions I've read on this subject get UTC time from the time() function which gets the current time.
I've tried implementing the following which was pulled from C++ Reference.
The timestamp I'm trying to convert is a double, but I'm not sure how to actually use this value.
An example ts from my data set: 1512695257869
int main ()
{
double my_utc_ts; //value acquired from the data set
time_t rawtime;
struct tm * ptm;
time ( &rawtime ); //getting current time
//rawtime = my_utc_ts; //this is what I tried and is wrong, and results in a nullptr
ptm = gmtime ( &rawtime );
puts ("Current time around the World:");
printf ("Phoenix, AZ (U.S.) : %2d:%02d\n", (ptm->tm_hour+MST)%24, ptm->tm_min);
return 0;
}
After I'm able to convert it to a usable gmtime object or whatever, I need to get seconds past the hour... I think I'll be able to figure this part out if I can get the UTC timestamps to successfully convert, but I haven't thought this far ahead.
Guidance would be much appreciated. Thanks in advance.
After I'm able to convert it to a usable gmtime object or whatever, I need to get seconds past the hour...
Here is how you can convert a double representing milliseconds since 1970-01-01 00:00:00 UTC to seconds past the local hour using Howard Hinnant's, free, open-source, C++11/14/17 timezone library which is based on <chrono>:
#include "date/tz.h"
#include <iostream>
int
main()
{
using namespace std::chrono;
using namespace date;
double my_utc_ts = 1512695257869;
using ms = duration<double, std::milli>;
sys_time<milliseconds> utc_ms{round<milliseconds>(ms{my_utc_ts})};
auto loc_s = make_zoned(current_zone(), floor<seconds>(utc_ms)).get_local_time();
auto sec_past_hour = loc_s - floor<hours>(loc_s);
std::cout << utc_ms << " UTC\n";
std::cout << sec_past_hour << " past the local hour\n";
}
This outputs for me:
2017-12-08 01:07:37.869 UTC
457s past the local hour
If your local time zone is not an integral number of hours offset from UTC, the second line of output will be different for you.
Explanation of code:
We start with your input my_utc_ts.
The next line creates a custom std::chrono::duration that has double as the representation and milliseconds as the precision. This type-alias is named ms.
The next line constructs utc_ms which is a std::chrono::time_point<system_clock, milliseconds> holding 1512695257869, and represents the time point 2017-12-08 01:07:37.869 UTC. So far, no actual computation has been performed. Simply the double 1512695257869 has been cast into a type which represents an integral number of milliseconds since 1970-01-01 00:00:00 UTC.
This line starts the computation:
auto loc_s = make_zoned(current_zone(), floor<seconds>(utc_ms)).get_local_time();
This creates a {time_zone, system_time} pair capable of mapping between UTC and a local time, using time_zone as that map. It uses current_zone() to find the computer's current time zone, and truncates the time point utc_ms from a precision of milliseconds to a precision of seconds. Finally the trailing .get_local_time() extracts the local time from this mapping, with a precision of seconds, and mapped into the current time zone. That is, loc_s is a count of seconds since 1970-01-01 00:00:00 UTC, offset by your-local-time-zone's UTC offset that was in effect at 2017-12-08 01:07:37 UTC.
Now if you truncate loc_s to a precision of hours, and subtract that truncated time point from loc_s, you'll get the seconds past the local hour:
auto sec_past_hour = loc_s - floor<hours>(loc_s);
The entire computation is just the two lines of code above. The next two lines simply stream out utc_ms and sec_past_hour.
Assuming that your local time zone was offset from UTC by an integral number of hours at 2017-12-08 01:07:37 UTC, you can double-check that:
457 == 7*60 + 37
Indeed, if you can assume that your local time zone is always offset from UTC by an integral number of hours, the above program can be simplified by not mapping into local time at all:
sys_time<milliseconds> utc_ms{round<milliseconds>(ms{my_utc_ts})};
auto utc_s = floor<seconds>(utc_ms);
auto sec_past_hour = utc_s - floor<hours>(utc_s);
The results will be identical.
(Warning: Not all time zones are offset from UTC by an integral number of hours)
And if your database is known to be generated with a time zone that is not the computer's current local time zone, that can be taken into account by replacing current_zone() with the IANA time zone identifier that your database was generated with, for example:
auto loc_s = make_zoned("America/New_York", floor<seconds>(utc_ms)).get_local_time();
Update
This entire library is based on the std <chrono> library introduced with C++11. The types above utc_ms and loc_s are instantiations of std::chrono::time_point, and sec_past_hour has type std::chrono::seconds (which is itself an instantiation of std::chrono::duration).
durations can be converted to their "representation" type using the .count() member function. For seconds, this representation type will be a signed 64 bit integer.
For a more detailed video tutorial on <chrono>, please see this Cppcon 2016 presentation. This presentation will encourage you to avoid using the .count() member function as much as humanly possible.
For example instead of converting sec_past_hour to a long so that you can compare it to other values of your dataset, convert other values of your dataset to std::chrono::durations so that you can compare them to sec_past_hour.
For example:
long other_data = 123456789; // past the hour in microseconds
if (microseconds{other_data} < sec_past_hour)
// ...
This snippet shows how <chrono> will take care of units conversions for you. This means you won't make mistakes like dividing by 1,000,000 when you should have multiplied, or spelling "million" with the wrong number of zeroes.
I'd start by converting the floating point number to a time_t. A time_t is normally a count of seconds since an epoch (most often the POSIX epoch--midnight, 1 Jan 1970), so it sounds like that's going to take little more than a bit of fairly simple math.
So let's assume for the sake of argument that your input uses a different epoch. Just for the sake of argument let's assume it's using an epoch of midnight, 1 jan 1900 instead (and, as noted, it's in milliseconds instead of seconds).
So, to convert that to a time_t, you'd start by dividing by 1000 to convert from milliseconds to seconds. Then you'd subtract off the number of seconds between midnight 1 jan 1900 and midnight 1 jan 1970. Now you have a value you can treat as a time_t that the standard library can deal with1.
Then use localtime to get that same time as a struct tm.
Then zero out the minutes and seconds from that tm, and use mktime to get a time_t representing that time.
Finally, use difftime to get the difference between the two.
1. For the moment, I'm assuming your standard library is based around a standard POSIX epoch, but that's a pretty safe assumption.
I am trying to capture packets from the NIC and save part of the packet payload as a string.
On part of packet that must be stored is its Log Time known as SysLog. Each packets has a SysLog with the following Format:
Nov 01 03 14:50:25 TCP...[other parts of packet Payload]
As it can be seen, the packet SysLog has no Year Number. My program must be running all over the year, so I need to add Year Number to the packet SysLog and convert SysLog to epoch time. The final string that I have to store is like this:
1478175389-TCP, ….
I use the following peace of code to convert Syslog to EpochTime.
tm* tm_date = new tm();
Std ::string time = Current_Year;
time += " ";
time += packet.substr(0,18);
strptime(time.c_str(), "%Y %b %d %T", tm_date);
EpochTime = timegm(tm_date);
The currentYear Method:
std::string currentYear() {
std::stringstream now;
auto tp = std::chrono::system_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());
size_t modulo = ms.count() % 1000;
time_t seconds = std::chrono::duration_cast<std::chrono::seconds>(ms).count();
#if HAS_STD_PUT_TIME
#else
char buffer[25]; // holds "2013-12-01 21:31:42"
if (strftime(buffer, 25, "%Y", localtime(&seconds))) {
now << buffer;
}
#endif // HAS_STD_PUT_TIME
return now.str();
}
The above operations are what i have to do for every packets. The packet rate is 100000-1000000 pps and the above peace of code is very time consuming specially on currentYear().
One possible optimization is to remove currentYear() Method and save the
Year number as a constant value. As said earlier my program must be run all over the year and as you know 2017 is comming. We can not change our binary at 31/12/2016 23:59:00 and also we don’t want to waste our time for calculating Year Number!!
I need a more efficient way to calculate the current year number without running it for each packet.
Is it possible? What is your suggestion for me?
Once you have obtained the current date and time, based on this it shouldn't be too difficult to calculate what the epoch time will be for midnight of next January 1st.
After calculating the expected epoch time for when the year rolls around, going forward all you have to do is compare it to the current time, when making a log entry. If it hasn't reached the precalculated Jan 1 midnight time, you know that the year hasn't rolled around yet.
So, you don't need to calculate the year for every packet at all. Just need to check the current time against the precalculated January 1st midnight time, which shouldn't change unless the politicians decide to change your timezone, while all of this is running...
The year is changed for log entries beginning with Jan, and only those log entries.
Log entries sometimes come out of order, or carry a timestamp saved during previous processing.
Attaching the year from the PC clock will give bad results, such as
2016 Dec 31 23:59:58 normal
2016 Jan 01 00:01:01 printing time placed in packet by remote device, remote clock is running a bit fast
2017 Dec 31 23:59:59 printing timestamp saved locally two seconds before logging occurred
2017 Jan 01 00:00:03 back to normal
You can't just concatenate the year of local clock with the month...second of the log message. You have to assign the year that avoids large clock jumps.
Since you're trying to produce Unix time (seconds since epoch) anyway, start by turning the log message time into Julian (seconds since start of year) and test whether the Julian is less than or greater than say 10 million (roughly 4 months).
You can "cache" the string you generate and only change it when the year changes. It may be though just a "little" improvement depending on what operations take the most time.
//somewhere
static int currentYear = 0;
static std::string yearStr = "";
//in your function
auto now = std::chrono::system_clock::now();
auto tnow = system_clock::to_time_t(now);
auto lt = localtime(&tnow); //or gmtime depends on your needs.
if(currentYear != lt.tm_year)
{
yearStr = std::to_string(lt.tm_year + 1900);
currentYear = t.tm_year;
}
return yearStr;
I am not sure if static has any negative/positive aspects on the performance of reading the string or a member variable may be better here due to cache locality. You have to test this.
If you use this in multiple threads you have to use a mutex here which probably will reduce performance though (again you have to measure this).
First, you might consider currentYear() returning an int (e.g. 2016), probably with time(2), localtime_r(3), the tm_year field.... You'll then avoid making C++ strings.
Then, you speak of high packet rate, so you probably have some event loop. You don't explain how it is done (hopefully you use some library à la libevent, or at least your own loop around poll(2)....), but you might compute the current year only once every tenth of second in that event loop. Or have some other thread computing the current year once in a while (you'll probably need a mutex, or use std::atomic<int> as the type of current year...)
I need an accurate conversion in my class from UTC time to local time of a given timezone, with or without DST in effect. My problem is, that when I use struct tm I have to provide the tm_isdst member, or leave it -1 to be determined automatically.
from mktime(3) - linux man page:
"The value specified in the tm_isdst field informs mktime() whether or not daylight saving time (DST) is in effect for the time supplied in the tm structure:
a positive value means DST is in effect;
zero means that DST is not in effect;
and a negative value means that mktime() should (use timezone information and system databases to) attempt to determine whether DST is in effect at the specified time.
Now here's my problem. I'm working with exchanges from all over the globe (from Chicago, New York, Sao Paolo, Melbourne, Buenos Aires, Johannesburg, Shanghai, Seoul ...). I have a table with the name of each timezone for each of the exchanges: for example Africa/Johannesburg, America/Chicago, America/Winnipeg.
The data I'm working on is expiration for some given futures and options financial instruments. The data I'm receiving is always in UTC, and I need to convert to the local time of the exchange.
Long story short, my current implementation is adding 1 extra hour to the expiration time of those assets that should not have the DST in effect (for example an instrument that expires in December and local time is America/Chicago, should add -360 minutes offset and DST 0, while another one which expires in June in the same timezone should have -360 timezone offset +60 DST offset, which would be -300 offset to the UTC timestamp. What I'm currently having the problem with, for example for the month of December I get 9:30 AM instead of 8:30 AM as the UTC timestamp contains the dst offset already.
Here is my function for doing the conversion, which is obviously broken:
#ifdef WIN32
#define timegm _mkgmtime
#endif
SimpleDateTime BusinessDateCalculator::UTC2TZ(const SimpleDateTime& utcDateTime, const int tz_utc_offset, const int tz_dst)
{
struct tm stm;
memset(&stm, 0, sizeof(stm));
stm.tm_year = utcDateTime.getYear() - 1900;
stm.tm_mon = utcDateTime.getMonth() - 1;
stm.tm_mday = utcDateTime.getDay();
stm.tm_hour = utcDateTime.getHour();
stm.tm_min = utcDateTime.getMinute();
stm.tm_sec = utcDateTime.getSecond();
stm.tm_isdst = -1; //see note at the top of this file
time_t tt = timegm( &stm );
tt += (tz_utc_offset + tz_dst) * 60;
struct tm ntm;
memset(&ntm, 0, sizeof(ntm));
gmtime_r( &tt, &ntm );
return SimpleDateTime(ntm.tm_year + 1900, ntm.tm_mon + 1, ntm.tm_mday, ntm.tm_hour, ntm.tm_min, ntm.tm_sec, utcDateTime.getMillisecond());
}
Where SimpleDateTime is a date-time class with additional functionality, like conversion from different date/time formats (SQL, FIX, Timeonly, DateOnly).
I have the timezone information of a certain exchange available at all time. My question can I provide the timezone name somehow, and let the timegm perform a database search and determine whether in the America/Chicago timezone the DST is or is not in effect on 2014-12-19 and accordingly not add the extra 60 minutes to the UTC time, and on the same date for example in the southern hemisphere timezone America/Sao_Paulo it is in effect until 16 Feb 2015, and for this timestamp it should add 60 minutes to get the correct local time for the given date.
When you refer to a time zone by it's IANA identifier (eg "America/Chicago") - that already includes all of the DST information and full history of the time zone. At least, it does in the original source data in the IANA time zone database.
You mentioned Boost (in comments). While Boost does have support for these types of identifiers, it makes the mistake of assuming that they are permanently fixed in time. That is not true, as time zones of the world change their offsets and DST rules all the time. Consider that the USA changed its DST rules in 2007, and that Russia is changing its time zones significantly later this year (Oct. 2014). If you look at the Boost time zone data file, you'll see that its format strips away all of the history and just maps each identifier to a single set of rules. For this reason, I recommend you do not use Boost for local time zone conversions.
Instead, consider using ICU. Among other things, it includes time zone conversion functions, and uses the full copy of the IANA time zone database. You can read more here, and see sample code here. I'm not particularly skilled in C++, but it would appear that you can use ICU's Calendar class to project a UTC time to a local time in a particular time zone.
Another option would be to use the time zone functions built in to the GNU C library. It also uses the full time zone database. There's a simple example of converting UTC tor local time using an IANA/Olson identifier on this site, which I have also posted below:
/*
C source code example: Convert UTC to local time zone, considering daylight
savings. Uses mktime(), gmtime() and localtime(). Works for dates between
years 1902 and 2037. Should compile and run with any recent GNU C if your
tzdata is healthy. Written by Robert Larsson http://rl.se
Code put in public domain; do what you want with it.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DESTZONE "TZ=Europe/Stockholm" // Our destination time zone
int main(void)
{
struct tm i;
time_t stamp; // Can be negative, so works before 1970
putenv("TZ=UTC"); // Begin work in Greenwich …
i.tm_year = 2009-1900; // Populate struct members with
i.tm_mon = 8-1; // the UTC time details, we use
i.tm_mday = 29; // 29th August, 2009 12:34:56
i.tm_hour = 12; // in this example
i.tm_min = 34;
i.tm_sec = 56;
stamp = mktime(&i); // Convert the struct to a Unix timestamp
putenv(DESTZONE); // Switch to destination time zone
printf("UTC : %s", asctime(gmtime(&stamp)));
printf("Local: %s", asctime(localtime(&stamp)));
return 0; // That’s it, folks.
}
I am trying to retrieve Current Time in milliseconds using boost library.. Below is my code which I am using to get the current time in milliseconds.
boost::posix_time::ptime time = boost::posix_time::microsec_clock::local_time();
boost::posix_time::time_duration duration( time.time_of_day() );
std::cout << duration.total_milliseconds() << std::endl;
uint64_t timestampInMilliseconds = duration.total_milliseconds() // will this work or not?
std::cout << timestampInMilliseconds << std::endl;
But this prints out in 10 digit which is like 17227676.. I am running my code on my ubuntu machine.. And I believe it is always 13 digit long value? Isn't so?
After computing the timestamp in milliseconds, I need to use below formula on that -
int end = (timestampInMilliseconds / (60 * 60 * 1000 * 24)) % 14
But somehow I am not sure whether timestampInMilliseconds which I am getting is right or not?
First of all should I be using boost::posix or not? I am assuming there might be some better way.. I am running code on my ubuntu machine..
Update:-
As this piece of bash script prints out timestampInMilliseconds which is of 13 digit..
date +%s%N | cut -b1-13
The problem here is that you use time_of_day() which returns (from this reference)
Get the time offset in the day.
So from the value you provided in the question I can deduce that you ran this program at 4:47 am.
Instead you might want to use e.g. the to_tm() to get a struct tm and construct your time in milliseconds from there.
Also note that the %s format to the date command (and the strftime function) is the number of seconds since the epoch, not the number of milliseconds.
If you look at the tm structure, you will see that it has the number of years (since 1900, so subtract 70 here), days into the year, and then hours,, minutes and seconds into the day. All these can be used to calculate the time in seconds easily.
And that in seconds is the problem here. If you look at e.g. the POSIX time function you see that
shall return the value of time in seconds since the Epoch
If you want an accurate millisecond resolution you simply can't use the ptime (where the p stands for POSIX). If you want millisecond resolution you either have to use e.g. system functions that returns the time in higher resolutions (like gettimeofday), or you can see e.g. this old SO answer.
I need to convert some string times in the format "2011061411322100" into GMT - my first attempt is below. However, the problem is that the times are coming from another PC and is a historical time. So I am not getting the times in real time so I cannot simply get the GMT from the local time on the box that my code is running.
The problem is that if my code is running during a time change, the time change will have occurred on my box but not on the remote box where I am getting the times. I can however, query the box to get the current time at any time.
So, to give more detail:
I start the job on a remote box
The job completes
I get some times related to the job running
I convert the time to GMT
If a time change (daylight savings) occurs between 1. and 2. I am screwed. My GMT conversion will break. I guess after 2) I need to get the current Remote Box time and see if there is a difference of >58 mins and then apply that to the conversion. But I cannot figure out a reliable method of doing this.
string GMTConverter::strToGMT(const string& timeToConvert)
{
// Set time zone from TZ environment variable.
_tzset();
struct tm tmTime;
//2011 06 14 11 32 21 00
// (strToInt is just a wrapper for atoi)
int year = strToint(timeToConvert.substr(0, 4) );
int month = strToint(timeToConvert.substr(4, 2) );
int day = strToint(timeToConvert.substr(6, 2) );
int hour = strToint(timeToConvert.substr(8, 2) );
int min = strToint(timeToConvert.substr(10, 2) );
int sec = strToint(timeToConvert.substr(12, 2) );
cout<<"Time after parsing: "<<year<<"/"<<month<<"/"<<day<<" "<<hour<<":"<<min<<":"<<sec<<endl;
// add to tm struct and return
tmTime.tm_hour = hour;
tmTime.tm_min = min;
tmTime.tm_sec = sec;
tmTime.tm_mday = day;
tmTime.tm_mon = (month-1);
tmTime.tm_year = (year - 1900);
cout <<"Time in TM: "<<tmTime.tm_year<<"/"<<tmTime.tm_mon<<"/"<<tmTime.tm_mday<<" "<<tmTime.tm_hour<<":"<<tmTime.tm_min<<":"<<tmTime.tm_sec<<endl;
char currDateTime[64];
// For logging
strftime(currDateTime, 63, "%c", &tmTime);
cout <<"Actual time:"<<currDateTime<<endl;
time_t remotePCTime = mktime( &tmTime );
struct tm *gmt = gmtime( &remotePCTime );
cout << "gmt = " << asctime( gmt ) << endl;
char datebuf_2[12];
char timebuf_2[13];
strftime( datebuf_2, 13, "%Y-%m-%d\0", gmt );
strftime( timebuf_2, 13, "%H:%M:%S\0", gmt );
return string(datebuf_2) + "T" + string(timebuf_2) + "." + string("000");
}
The obvious reliable solution would be to use UTC (which has no daylight savings) for the time stamp you're sending over. Using any time system that has inherent ambiguity (there is one hour of overlap each year where you can get the same time stamps on a different time) will make it impossible to have a fool-proof method, since information is lost.
If you have no control over the time format that the remote machine is sending, you can only try to extrapolate from the information that you do have, for instance, if the end time is lower than the start time, add one hour. This again introduces ambiguity if the job took longer than one hour, but at least time won't move backwards.
Time change appears twice a year - why should you bother? Anyway, can't you change the time format to include the time change event? Or check if job is done during time change by comparing to some fixed time and date at which time change appears?
Get the local time in UTC at the start and end of the remote job. Get the remote job time and covert to UTC at the start and end of the job. Convert the collection "historic" times to GMT/UTC as stated in your original post. Keep this data together in a struct or class and give additional start end times a clear name like LocalDLSValidation etc
We must now checkfor following scenarios:
1. Start and end time delta between Local and Remote is within allowed threshold(50mins?)
This the gold case. No modification is required to our collection of historical times
2. Local start/end time and remote time delta is outside threshold.
This is the second simplest case. It means that we can + or - hour to our entire collection of times.
3.Local start time and remote time delta is within threshold. But end is outside.
This is our worst case scenario as it means change has occurred in the middle of our job. If the job lasts less than hour then it will be easy to see which times in our collection need to be + or - one hour.
If it is greater than 1 hour....mmmmm. This is where we run into problems.
4. Start time between local and remote is different but end time is different
According to use case in OP this should not occur.