<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Correctly calculating hours between two times in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555691#M154666</link>
    <description>&lt;P&gt;Unfortunately I'm not well-versed in many programming languages, so I can't say for sure. I thought that the "lubridate" package in R had that functionality, but I may be mistaken. I know too that some R functions for fitting longitudinal or time series models (for example, the temporal smoothers in the "mgcv" package) have ways of taking the "wrapping around" of time or date variables into account, but the application is different.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;On one hand, it makes sense why this is limitation exists, since the typical programming solution is to encode times as the number of seconds relative to some benchmark (e.g. midnight). On the other hand, it's a very simple mathematical operation, so it would surprise me if there were NO solutions to this. Even something as simple as having an option to the "intck" function that says "crossdays=TRUE" or something to that effect.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Anyway, thank you for your response! It looks like I am just going to have to code something clunky (unfortunately I don't have date variables for both days, I only have date variables for the first day, and some people went to sleep past midnight, so I am going to have to do an if/then loop or two to make the calculations work for everyone).&lt;/P&gt;</description>
    <pubDate>Thu, 02 May 2019 17:48:23 GMT</pubDate>
    <dc:creator>RyanSimmons</dc:creator>
    <dc:date>2019-05-02T17:48:23Z</dc:date>
    <item>
      <title>Correctly calculating hours between two times</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555657#M154645</link>
      <description>&lt;P&gt;I have a dataset full of times, indicating when an individual went to bed at night and when they woke up the next morning. I want to create a new variable that indicates the number of hours that they were asleep. However, SAS doesn't seem to understand how clocks work, and is unable to "wrap" times around the clock to do the calculation in a sensible way.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For example, if someone went to bed at 9pm and woke up at 5am, we would WANT the value of hours slept to be 8. However, SAS will return +/- 16, since it is only able to calculate the difference in a linear fashion. There are a couple of workarounds to this (included in my code snippet below), but they feel very clunky to me. One of them is pulling in the date variables and using the dhms function and then converting the result into hours, the other is converting the bedtime variable into the # of hours before midnight and then adding that to the wake up time variable.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here's an example:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA time;
	/* Bed time and wakey time */
	bed_time = 75600; format bed_time time8.;
	wake_time = 18000; format wake_time time8.;

	/* Wrong answer */
	wrong_hours_slept = intck('hour',bed_time,wake_time);

	/* Clunky solution 1 */
	day1 = today(); format day1 date8.;
	day2 = intnx('day',day1,1); format day2 date8.;
	seconds_slept = dhms(day2,0,0,wake_time) - dhms(day1,0,0,bed_time);
	right_hours_slept1 = seconds_slept/3600;

	/* Clunky solution 2 */
	hours_before_midnight = (86400 - bed_time)/3600;
	right_hours_slept2 = hours_before_midnight + wake_time/3600;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Are there any other solutions? Obviously both of the above work, and ultimately don't require too much extra coding, but it feels rather frustrating to me that SAS doesn't have a built-in way of manipulating clock time. Further, both of these clunky solutions also have points of failure (notably with people who go to sleep after midnight), requiring some if/then logic to correct.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 02 May 2019 16:58:27 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555657#M154645</guid>
      <dc:creator>RyanSimmons</dc:creator>
      <dc:date>2019-05-02T16:58:27Z</dc:date>
    </item>
    <item>
      <title>Re: Correctly calculating hours between two times</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555666#M154649</link>
      <description>&lt;P&gt;Are you aware of any implementation in any programming language that does account for times that cross days? Genuinely curious.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Regarding SAS, you need to add the dates to get the times to be handled correctly. There's no way around that.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Ideally you'd have the dates included in the data not just time and use a datetime variables - just subtracting them would solve the problem, which you're already determined.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
set have;

sleep_start = dhms(date_start, 0, 0, time_start);
sleep_end = dhms(date_end, 0, 0, time_end);

Hours_slept = sleep_end - sleep_start / (60*60); *result is in seconds, convert to hours;

run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 02 May 2019 17:15:14 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555666#M154649</guid>
      <dc:creator>Reeza</dc:creator>
      <dc:date>2019-05-02T17:15:14Z</dc:date>
    </item>
    <item>
      <title>Re: Correctly calculating hours between two times</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555669#M154652</link>
      <description>&lt;P&gt;I really like your question. Since the understanding largely involves number of seconds since midnight(time) vs number of seconds from Jan1,1960(Datetime)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Your approach to create a datetime value and then compute arithmetic to create hours seems to be the only thing or right thing to do.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Considering the case of sleeping hours mandates datetime values, I wonder how otherwise this can be done, i.e besides the scope of having a convoluted expression like&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
bed_time = 75600; format bed_time time8.;
wake_time = 18000; format wake_time time8.;
hours_slept = intck('hour', dhms(today()-1,0,0,bed_time),dhms(today(),0,0,wake_time));
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 02 May 2019 17:18:20 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555669#M154652</guid>
      <dc:creator>novinosrin</dc:creator>
      <dc:date>2019-05-02T17:18:20Z</dc:date>
    </item>
    <item>
      <title>Re: Correctly calculating hours between two times</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555691#M154666</link>
      <description>&lt;P&gt;Unfortunately I'm not well-versed in many programming languages, so I can't say for sure. I thought that the "lubridate" package in R had that functionality, but I may be mistaken. I know too that some R functions for fitting longitudinal or time series models (for example, the temporal smoothers in the "mgcv" package) have ways of taking the "wrapping around" of time or date variables into account, but the application is different.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;On one hand, it makes sense why this is limitation exists, since the typical programming solution is to encode times as the number of seconds relative to some benchmark (e.g. midnight). On the other hand, it's a very simple mathematical operation, so it would surprise me if there were NO solutions to this. Even something as simple as having an option to the "intck" function that says "crossdays=TRUE" or something to that effect.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Anyway, thank you for your response! It looks like I am just going to have to code something clunky (unfortunately I don't have date variables for both days, I only have date variables for the first day, and some people went to sleep past midnight, so I am going to have to do an if/then loop or two to make the calculations work for everyone).&lt;/P&gt;</description>
      <pubDate>Thu, 02 May 2019 17:48:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555691#M154666</guid>
      <dc:creator>RyanSimmons</dc:creator>
      <dc:date>2019-05-02T17:48:23Z</dc:date>
    </item>
    <item>
      <title>Re: Correctly calculating hours between two times</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555692#M154667</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/46908"&gt;@RyanSimmons&lt;/a&gt;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;How about this?&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;right_hours_slept = 24*(bed_time&amp;gt;wake_time)+(wake_time-bed_time)/3600;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Note that your&amp;nbsp;&lt;FONT face="courier new,courier"&gt;right_hours_slept1&lt;/FONT&gt; and&amp;nbsp;&lt;FONT face="courier new,courier"&gt;right_hours_slept2&lt;/FONT&gt; values (unlike the above expression) would need a correction if someone went to bed after midnight.&lt;/P&gt;</description>
      <pubDate>Thu, 02 May 2019 17:51:09 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555692#M154667</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2019-05-02T17:51:09Z</dc:date>
    </item>
    <item>
      <title>Re: Correctly calculating hours between two times</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555727#M154679</link>
      <description>&lt;P&gt;Interesting! Clever idea. Looks like this is essentially the same logic as my "clunky solution 2", but operationalized better. I'll leave this question open for a little while longer to see if anybody else comes up with something clever, otherwise I think this will be the answer!&lt;/P&gt;</description>
      <pubDate>Thu, 02 May 2019 18:55:35 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555727#M154679</guid>
      <dc:creator>RyanSimmons</dc:creator>
      <dc:date>2019-05-02T18:55:35Z</dc:date>
    </item>
    <item>
      <title>Re: Correctly calculating hours between two times</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555751#M154690</link>
      <description>&lt;P&gt;SAS has all the tools needed for time calculations. The idea is to stay away from the internal representation of data and time values with date and time literals. In time literals, a day is '24:00:00't and an hour is '1:00:00't.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA time;
	/* Bed time and wakey time */
	bed_time = '21:00:00't; format bed_time time9.;
	wake_time = '24:00:00't + '05:00:00't; format wake_time time9.;

	hours_slept = (wake_time - bed_time) / '1:00:00't;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;or if you prefer&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA time;
	/* Bed time and wakey time */
	bed_time = '21:00:00't; format bed_time time9.;
	wake_time = '05:00:00't; format wake_time time9.;

	hours_slept = ('24:00:00't + wake_time - bed_time) / '1:00:00't;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;s &lt;/P&gt;</description>
      <pubDate>Thu, 02 May 2019 20:16:16 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555751#M154690</guid>
      <dc:creator>PGStats</dc:creator>
      <dc:date>2019-05-02T20:16:16Z</dc:date>
    </item>
    <item>
      <title>Re: Correctly calculating hours between two times</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555769#M154705</link>
      <description>&lt;P&gt;Here's a shorter expression which avoids the repetition of variable names:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;right_hours_slept = mod(24+(wake_time-bed_time)/3600,24);&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 02 May 2019 21:07:59 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/555769#M154705</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2019-05-02T21:07:59Z</dc:date>
    </item>
    <item>
      <title>Re: Correctly calculating hours between two times</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/729148#M226878</link>
      <description>&lt;P&gt;Hello! This really helped me and allowed me to calculate the correct number of hours between two times. However, I am having difficulty picking the code apart. Would you be able to explain each argument in some more detail to help me understand?&lt;/P&gt;&lt;P&gt;Thanks so much in advance for your consideration.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 25 Mar 2021 17:41:28 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/729148#M226878</guid>
      <dc:creator>repchur</dc:creator>
      <dc:date>2021-03-25T17:41:28Z</dc:date>
    </item>
    <item>
      <title>Re: Correctly calculating hours between two times</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/729256#M226920</link>
      <description>&lt;P&gt;Hello&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/337288"&gt;@repchur&lt;/a&gt;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Glad to hear that my old post helped you, too.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Basically, we had to apply one of two formulas to compute variable &lt;FONT face="courier new,courier"&gt;right_hours_slept&lt;/FONT&gt;:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT face="courier new,courier"&gt;(wake_time-bed_time)/3600&lt;/FONT&gt; if &lt;FONT face="courier new,courier"&gt;bed_time&lt;/FONT&gt;&amp;nbsp;is "at or after midnight." In this case both times belong to the same date and &lt;FONT face="courier new,courier"&gt;wake_time&amp;gt;bed_time&lt;/FONT&gt;. Therefore, dividing the (positive) difference of the SAS time values (i.e., numbers of seconds after midnight of that same date) by 3600 gives us the time difference in hours rather than seconds.&lt;/LI&gt;
&lt;LI&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRONG&gt;24+&lt;/STRONG&gt;(wake_time-bed_time)/3600&lt;/FONT&gt; if &lt;FONT face="courier new,courier"&gt;bed_time&lt;/FONT&gt;&amp;nbsp;is "before midnight."&amp;nbsp;In this case we assume that &lt;FONT face="courier new,courier"&gt;bed_time&lt;/FONT&gt; and &lt;FONT face="courier new,courier"&gt;wake_time&lt;/FONT&gt; belong to two consecutive days and that &lt;FONT face="courier new,courier"&gt;bed_time&amp;gt;wake_time&lt;/FONT&gt;.&amp;nbsp;Therefore, variable &lt;FONT face="courier new,courier"&gt;right_hours_slept&lt;/FONT&gt;&amp;nbsp;can be computed as the sum of the time (in hours) from &lt;FONT face="courier new,courier"&gt;bed_time&lt;/FONT&gt; until midnight, which is &lt;FONT face="courier new,courier"&gt;24-bed_time/3600&lt;/FONT&gt;, and the time from midnight until &lt;FONT face="courier new,courier"&gt;wake_time&lt;/FONT&gt;, which is &lt;FONT face="courier new,courier"&gt;wake_time/3600&lt;/FONT&gt;, resulting in said formula.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;What happens if we (incorrectly) apply the formula of case 2 to case 1? The correct, positive number of hours slept (for example, 7.5) is increased by 24 (result: 31.5 in the example).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now the function &lt;EM&gt;f&lt;/EM&gt;(&lt;EM&gt;x&lt;/EM&gt;)=mod(&lt;EM&gt;x&lt;/EM&gt;, 24) comes to the rescue because for a non-negative value &lt;EM&gt;x&lt;/EM&gt;, written in the form 24*&lt;EM&gt;n&lt;/EM&gt;+&lt;EM&gt;r&lt;/EM&gt; with a non-negative integer &lt;EM&gt;n&lt;/EM&gt; and a remainder &lt;EM&gt;r&lt;/EM&gt; with 0&amp;lt;=&lt;EM&gt;r&lt;/EM&gt;&amp;lt;24, it yields &lt;EM&gt;r&lt;/EM&gt;. (Divide &lt;EM&gt;x&lt;/EM&gt; by 24 to obtain the integer part &lt;EM&gt;n&lt;/EM&gt; of the quotient and the remainder &lt;EM&gt;r&lt;/EM&gt;, both uniquely determined.)&amp;nbsp;That is, any additional integer multiple of 24, be it 24, 48 or 72, etc., is deducted while the remainder is left unchanged: &lt;EM&gt;f&lt;/EM&gt;(&lt;EM&gt;x&lt;/EM&gt;)=&lt;EM&gt;f&lt;/EM&gt;(&lt;EM&gt;r&lt;/EM&gt;)=&lt;EM&gt;r&lt;/EM&gt;&amp;nbsp;for all &lt;EM&gt;n&lt;/EM&gt;=0, 1, 2, ...&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In our application of &lt;EM&gt;f&lt;/EM&gt; to the expression&amp;nbsp;&lt;FONT face="courier new,courier"&gt;24+(wake_time-bed_time)/3600&lt;/FONT&gt;&amp;nbsp;only two different values of &lt;EM&gt;n&lt;/EM&gt; occur:&amp;nbsp;&lt;EM&gt;n&lt;/EM&gt;=0 for the correct result in case 2 (remember that &lt;FONT face="courier new,courier"&gt;wake_time-bed_time&lt;/FONT&gt; is negative here) and&amp;nbsp;&lt;EM&gt;n&lt;/EM&gt;=1 when the formula of case 2 is applied to case 1. So, the effect of function &lt;EM&gt;f&lt;/EM&gt; just amounts to subtracting the incorrectly added 24 (hours) in the latter case, while the correct result in the former case is left unchanged. Hence we've found a single formula that is applicable to case 1 &lt;EM&gt;and&lt;/EM&gt; case 2:&lt;/P&gt;
&lt;PRE class="language-sas"&gt;&lt;CODE&gt;right_hours_slept = mod(24+(wake_time-bed_time)/3600,24)&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 25 Mar 2021 22:54:07 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Correctly-calculating-hours-between-two-times/m-p/729256#M226920</guid>
      <dc:creator>FreelanceReinh</dc:creator>
      <dc:date>2021-03-25T22:54:07Z</dc:date>
    </item>
  </channel>
</rss>

