<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Converting local time from CTS to UTC time</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/90183/converting-local-time-from-cts-to-utc-time</link><description>Hi, 
 I&amp;#39;m currently reading the local time from a client via the CTS over BLE, but need to convert that in my nRF52832 to UTC time. Is there some API&amp;#39;s available that do this? I can&amp;#39;t seem to find any, and was thinking &amp;quot;surely, someone has done this before</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 22 Jul 2022 08:55:02 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/90183/converting-local-time-from-cts-to-utc-time" /><item><title>RE: Converting local time from CTS to UTC time</title><link>https://devzone.nordicsemi.com/thread/378241?ContentTypeID=1</link><pubDate>Fri, 22 Jul 2022 08:55:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:98919326-daff-4bec-898a-465043bee008</guid><dc:creator>Simon</dc:creator><description>&lt;p&gt;There you go. I&amp;#39;m glad you found a solution that works for you.&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Simon&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Converting local time from CTS to UTC time</title><link>https://devzone.nordicsemi.com/thread/378209?ContentTypeID=1</link><pubDate>Fri, 22 Jul 2022 05:20:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:f2159d13-5a4d-46ab-a93e-567f28f11c01</guid><dc:creator>Mike Austin (LPI)</dc:creator><description>&lt;p&gt;OK, ended up sorting this out for myself.&amp;nbsp; Below is my code.&amp;nbsp; I&amp;#39;m sure someone could make this more efficient, but I&amp;#39;m a hardware guy so just happy it works! Haha.&lt;/p&gt;
&lt;p&gt;At the moment I&amp;#39;m just hard coding the values for .timeZone and .dst into my bt_cts_local_time structure, as I&amp;#39;ve not yet been able to extract this from the CTS.&amp;nbsp; Plus it made it easier for me to test all the various scenarios.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;#define DAYS_IN_WEEK 7
#define MONTHS_IN_YEAR 12
#define MINS_IN_HOUR 60
#define HOURS_IN_DAY 24
#define JANUARY 1
#define FEBRUARY 2
#define MARCH 3
#define DECEMBER 12

/**
 * @brief CTS Local Time structure
 *
 * @param timeZone Offset from UTC in hours
 * @param dst Daylight Savings Time: 1 = active, 0 = inactive
 */
struct bt_cts_local_time
{
    int8_t timeZone;           /**&amp;lt; Current Time Zone */
    uint8_t dst;               /**&amp;lt; Daylight Saving Time value */
} ;

struct bt_cts_current_time local_time, utc_time;
struct bt_cts_local_time local_time_info;

uint8_t daysInMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

// Convert time from Current Time Service to UTC time
// cts_current_time = time from CTS
// cts_local_time = local time info (time zone and DST) from CTS
// utc_time = time converted to UTC
void convert_to_utc_time (struct bt_cts_current_time *cts_current_time, struct bt_cts_local_time *cts_local_time, struct bt_cts_current_time *utc_time)
{
    int8_t  minOffset = 0,
            hourOffset = 0,
            dayOffset = 0,
            monthOffset = 0,
            yearOffset = 0,
            days_in_current_month = 0,
            days_in_previous_month = 0;
    uint8_t week_day,
            day,
            month,
            hour,
            min;
    uint16_t year;
    bool isLeapYear;

    week_day = cts_current_time-&amp;gt;exact_time_256.day_of_week;
    day = cts_current_time-&amp;gt;exact_time_256.day;
    month = cts_current_time-&amp;gt;exact_time_256.month;
    hour = cts_current_time-&amp;gt;exact_time_256.hours;
    min = cts_current_time-&amp;gt;exact_time_256.minutes;
    year = cts_current_time-&amp;gt;exact_time_256.year;
    
    /* Calculate time offset due to local time zone and daylight savings */
    // .timeZone and .dst are expressed in multiples of 15 minutes
    // Negative offset means local time is behind UTC, positive offset means local time is ahead of UTC
    hourOffset = (int8_t)((cts_local_time-&amp;gt;timeZone/4) + (cts_local_time-&amp;gt;dst/4));
    minOffset = (int8_t)((cts_local_time-&amp;gt;timeZone%4) + (cts_local_time-&amp;gt;dst%4))*15;
    
    if (year%4 == 0) {
        isLeapYear = true;
        if (month == FEBRUARY) {
            days_in_current_month = daysInMonth[FEBRUARY]+1;
        }
        else {
            days_in_current_month = daysInMonth[month];
        }
        if (month == MARCH) {
            days_in_previous_month = daysInMonth[FEBRUARY]+1;
        }
        else if (month == JANUARY) {
            days_in_previous_month = daysInMonth[DECEMBER];
        }
        else {
            days_in_previous_month = daysInMonth[month-1];
        }
    }
    else {
        isLeapYear = false;
        if (month == JANUARY) {
            days_in_previous_month = daysInMonth[DECEMBER];
        }
        else {
            days_in_previous_month = daysInMonth[month-1];
        }
        days_in_current_month = daysInMonth[month];
    }

    /* Update mintues */
    if (minOffset &amp;lt; 0) { 
        //Local behind UTC - increase minutes  
        if ((min + abs(minOffset)) &amp;gt; MINS_IN_HOUR) {
            ++hourOffset;
            min = (min + abs(minOffset)) - MINS_IN_HOUR;
        }
        else {
            min = (min + abs(minOffset));
        }
    }
    else if (minOffset &amp;gt;= 0) {
        //Local ahead of UTC - reduce minutes  
        if (min &amp;lt; minOffset) {
            --hourOffset;
            min = MINS_IN_HOUR + min - minOffset;
        }
        else {
            min = min - minOffset;
        }
    }

    /* Update hours */
    if (hourOffset &amp;lt; 0) {
        //Local behind UTC - increase hours 
            if ((hour + abs(hourOffset)) &amp;gt; HOURS_IN_DAY) {
            ++dayOffset;
            hour = (hour + abs(hourOffset)) - HOURS_IN_DAY;
        }
        else {
            hour = (hour + abs(hourOffset));
        }
    }
    else if (hourOffset &amp;gt;= 0) {
        //Local ahead of UTC - reduce hours
        if (hour &amp;lt; hourOffset) {
            --dayOffset;
            hour = HOURS_IN_DAY + hour - hourOffset;
        }
        else {
            hour = hour - hourOffset;
        }
    }
    

    /* Update day of month */
    if (dayOffset &amp;gt;= 0) {
        if ((day + dayOffset) &amp;gt; days_in_current_month) {
        ++monthOffset;
        day = (day + dayOffset) - days_in_current_month;
    }
    else {
        day = day + dayOffset;
    }
    }
    else if (dayOffset &amp;lt; 0) {
        if (day &amp;lt;= abs(dayOffset)) {
            --monthOffset;
            day = days_in_previous_month + day + dayOffset;
        }
        else {
            day = day + dayOffset;
        }
    }

    /* Update month */
    if (monthOffset &amp;gt;= 0) {
        if ((month + monthOffset) &amp;gt; MONTHS_IN_YEAR) {
        ++yearOffset;
        month = (month + monthOffset) - MONTHS_IN_YEAR;
    }
    else {
        month = month + monthOffset;
    }
    }
    else if (monthOffset &amp;lt; 0) {
        if (month &amp;lt;= abs(monthOffset)) {
            --yearOffset;
            month = MONTHS_IN_YEAR + month + monthOffset;
        }
        else {
            month = month + monthOffset;
        }
    }
    
    /* Update day of week */
    if (dayOffset &amp;gt;= 0) {
        if ((week_day + dayOffset) &amp;gt; DAYS_IN_WEEK) {
            week_day = (week_day + dayOffset) - DAYS_IN_WEEK;
        }
        else {
            week_day = week_day + dayOffset;
        }
    }
    else if (dayOffset &amp;lt; 0) {
        if (week_day &amp;lt;= abs(dayOffset)) {
            week_day = DAYS_IN_WEEK + week_day + dayOffset;
        }
        else {
            week_day = week_day + dayOffset;
        }
    }
 
    /* Set UTC time */
    utc_time-&amp;gt;exact_time_256.seconds = cts_current_time-&amp;gt;exact_time_256.seconds;
    utc_time-&amp;gt;exact_time_256.minutes = min;
    utc_time-&amp;gt;exact_time_256.hours = hour;
    utc_time-&amp;gt;exact_time_256.day_of_week = week_day;
    utc_time-&amp;gt;exact_time_256.day = day;
    utc_time-&amp;gt;exact_time_256.month = month;
    utc_time-&amp;gt;exact_time_256.year = year + yearOffset;

}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Cheers,&lt;/p&gt;
&lt;p&gt;Mike&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Converting local time from CTS to UTC time</title><link>https://devzone.nordicsemi.com/thread/378027?ContentTypeID=1</link><pubDate>Thu, 21 Jul 2022 09:17:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e19a7312-2a8d-4597-94b5-baa4d85f1fd5</guid><dc:creator>Mike Austin (LPI)</dc:creator><description>&lt;p&gt;Yep, happy to bundle the two issues together.&lt;/p&gt;
&lt;p&gt;I just thought that someone might have done the heavy lifting on the UTC conversion before.&lt;/p&gt;
&lt;p&gt;Cheers,&lt;/p&gt;
&lt;p&gt;Mike&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Converting local time from CTS to UTC time</title><link>https://devzone.nordicsemi.com/thread/378024?ContentTypeID=1</link><pubDate>Thu, 21 Jul 2022 09:13:29 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:34c5f5b2-6e7d-4cc4-b057-e79aa2c71249</guid><dc:creator>Simon</dc:creator><description>&lt;p&gt;Hello Mike,&lt;/p&gt;
&lt;p&gt;Should we continue the discussion in&amp;nbsp;&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/90191/getting-time-zone-and-daylight-savings-info-out-of-cts"&gt;Getting Time Zone and Daylight Savings info out of CTS&lt;/a&gt;&amp;nbsp;?&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Simon&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>