GMT to Local Time Routine


+ Reply to Thread
Results 1 to 15 of 15
  1. #1

    Default GMT to Local Time Routine

    Can anyone point me in the right direction for how to convert GMT to a user defined local time?

    In my circumstances I am downloading the GMT network time using an ESP8266 (very slick module, by the way). I then successfully store the GMT time in a DS1307 RTC. Ok, works well.

    Now I need to convert GMT to local time. I am making a large (10cm) 4 digit LED display into a clock (don't we all make some kind of clock at some point in our quests?).

    I am using:
    • Pic Basic Pro version 3,
    • PIC16F886,
    • DS1307 (and PCF8583),
    • ESP8266
    I guess what I am thinking is that one would store the following parameters in the RTC EPROM storage:
    • TimeZone name
    • DST start date
    • DST end date
    • DST offset in minutes
    The time would be updated about every 10 minutes using the ESP8266 and writing to the RTC as GMT. Example string from ESP8266 is:

    15 Jul 2015 13:15:00 GMT

    I have already figured out how to read the string, convert the GMT string to the necessary DS1307 BCD numbers and upload it to the RTC via I2C. My next task is to call ClockGetLocal and have it store the local time in the ClkMin, ClkHrs, etc variables.

  2. #2
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,817


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    I never tried to code that, but seems simply to subtract 8 hours from (your location) GMT before you transfer to RTC.
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  3. #3
    Join Date
    Aug 2008
    Location
    Portugal
    Posts
    240


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    Hi;

    I allready do this, but not in PBP, however i will explain how i do it;
    After receiving the GMT you convert it to EpochTime
    Than you subtract the seconds to the EpochTime, for instance 8hourx3600 = 28800seconds
    Then you convert the subtracted EpochTime to Normal Time again, that will be your new time with the 8 hours subtracted.

    If you fo like Archangel said, you canno't only subtract the 8 hours, because we have to works out also the date, and not only time. Imagine its 2 am, if you subtract 8 hours it will be 6 pm, but the day will be diferent.
    Thanks and Regards;
    Gadelhas

  4. #4


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    Interesting ideas.

    Subtracting 8 hours does seem like a solution except I will need to take into account adding or subtracting enough MINUTES so that I accurately keep track of crossing midnight. The reason I say minutes is that some places have a local time with a 30 minute difference.

    Using Epoch time is interesting and I partially did that in the last couple of hours. However, I was worried that the number of minutes in a year exceeded the size of a WORD variable (LONG variables are part of the PIC 18F series and I am using a 16F).

    Later on today and with some more forum searching, I came up with a partial solution.

    Working on the premise that a large display clock only displays the hour and the minute, you only need to worry about the last 24 hours. Thus, you do not need to worry about a DAY OF MONTH, MONTH or YEAR change. That greatly shortens the code. I'll tackle those at a later date. Thus, my largest number would be 1440 minutes which will fit in a WORD variable.

    Next I needed to convert from BCD to DEC and back. Remember I am using BCD because the RTC stores it that way. I am using DEC to do the epoch calculations. A couple of posts on this forum provided some important clues.

    To convert BCD to DEC (I love the simplicity of it!)

    myDEC = ((myBCD >> 4) * 10) + (myBCD & $0F)

    To convert the DEC to BCD, the forum provided another clue by using the DIG mathematical operator (pg 74 in manual, sec 3.1.9):

    myBCD = ((myDEC DIG 1) * 16) + (myDEC DIG 0)

    Again, I did not invent these, they were found on the forum.

    CONVERTING TO LOCAL TIME:

    Remember I only have to do the hours and minutes for now (I have already burned too many brain cells on this project today, I'll tackle the rest at another date)

    ' ==== First I read the RTC and to bring the BCD values into ClkYear,ClkMon, etc

    ' ==== Next I convert all those BCD values to DEC so I can do Epoch calculations

    DstYear =((ClkYear >> 4) * 10) + (ClkYear & $0F) ' last two digits of year
    DstMon = ((ClkMon >> 4) * 10) + (ClkMon & $0F) ' Month starting at 01
    DstDte = ((ClkDte >> 4) * 10) + (ClkDte & $0F) ' Date of the month, i.e. the 13th
    DstDOW = ClkDOW ' Day of week (I don't use this)
    DstHrs = ((ClkHrs >> 4) * 10) + (ClkHrs & $0F) ' 24 hour clock
    DstMin = ((ClkMin >> 4) * 10) + (ClkMin & $0F) ' minutes
    DstSec = ((ClkSec >> 4) * 10) + (ClkSec & $0F) ' seconds

    ' ==== Now I make a mini epoch :-) of the last 24 hours
    ' ==== DstTime contains the number of minutes in minutes, hours and Day of the Month (DstDte)

    DstTime = DstMin + (DstHrs * 60) ' number of minutes in minutes and hours
    DstTime = DstTime + (DstDte * 1440) ' At this point you have a mini Epoch of the number of minutes in this month

    ' ==== Next subtract out the number of minutes from GMT.

    DstTime = DstTime - DstOffset ' for me in California, this is 7 hours * 60 minutes or 420 minutes


    ' ==== This won't work for most of the world, I just need to get something working for
    ' ==== where I live in California U.S.A. I'll work out the rest of the world later.
    ' ==== Also, this does not automatically change from DST to ST..... later, later, later

    ' ==== Finally, convert your mini Epoch to decimal times

    DstDte = DstTime / 1440 ' Day of the month
    DstHrs = (DstTime // 1440) / 60 ' Military Hours
    DstMin = (DstTime // 60) ' Minutes

    Hope that helps. Now I need to finish my project and then come back to this and make it into a usable set of functions. :-)

    Thank you all for the ideas!

    To-Do Ideas:
    1) Check to see what happens at month crossover. Need to allocate for months with different number of days and Feb with 29 days
    2) Once a month changes, check to see if year changed.
    3) Need a configuration file that has the name of the timezone, start of DST, end of DST and offset with plus/minus in minutes. Dates will likely be different from year to year (see http://www.timeanddate.com/time/dst/ )
    4) Need to store config file. How about in RTC which has 56 bytes of battery backed memory.
    5) When year changes, go look for config file and update config
    6) Tie all of this into a tutorial on how to interface the ESP8266 wifi module (about $3) so you don't have to use WWVB, GPS, etc.
    7) How to determine your approx location??? Does wifi module know physical location of gateway? That way you could set config automagically
    8) Is there an easy way to do BCD arithmetic?

    === End of Message ===

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    Oh, a couple of side notes:

    1) technically you do not need to worry about seconds because GMT to local time share the same seconds.

    2) if you want to ignore those places that do partial hours, you can eliminate minutes too. But be nice to India, Australia, Newfoundland, etc. :-)

  6. #6
    Join Date
    Aug 2003
    Location
    Australia
    Posts
    983


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    In Eastern Australia we are +10.

    You are lucky if you are only displaying 24 hour time, and not the date,
    or you need a full calendar all the way to checking leap years.
    Just the one hour ahead the hour before midnight on a New Year’s Eve,
    would make the entire date and day of week incorrect otherwise.

    The calendar code I have posted here has done fine on that with my testing so far.
    It is also the thing that tells you if any of it’s fields changed.

  7. #7


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    Thank you Art! I'll look at it.

  8. #8
    Join Date
    Aug 2008
    Location
    Portugal
    Posts
    240


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    Quote Originally Posted by Art View Post
    In Eastern Australia we are +10.

    You are lucky if you are only displaying 24 hour time, and not the date,
    or you need a full calendar all the way to checking leap years.
    Just the one hour ahead the hour before midnight on a New Year’s Eve,
    would make the entire date and day of week incorrect otherwise.
    Thats why its better working with EpochTime.
    Thanks and Regards;
    Gadelhas

  9. #9
    Join Date
    Aug 2003
    Location
    Australia
    Posts
    983


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    How do you not still need a calendar?.. You can calculate all you want from an epoch moment,
    how do you then know the day of week, or if a date such as the 45th of June 1955 is invalid?
    The calendar still counts from an epoch... you need to begin with a known leap year.

  10. #10
    Join Date
    Aug 2008
    Location
    Portugal
    Posts
    240


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    Quote Originally Posted by Art View Post
    How do you not still need a calendar?.. You can calculate all you want from an epoch moment,
    how do you then know the day of week, or if a date such as the 45th of June 1955 is invalid?
    The calendar still counts from an epoch... you need to begin with a known leap year.
    Hi Art;

    The Epoch/Unix time ( 32 bits ) its valid since 1970 to 1938. Probably it will be changed to 64bits and then it will be valid longer than the age of the universe. ( Probably )

    Several Industrial systems and Computer systems uses this aproach.
    You don't need a calender for nothing, you can calculate everything from epoch time, including day of week, and also if a some date is valid or not.
    By the way , to calculate day of week, or leap year you don't even need epoch time.

    References;

    Epoch/Unix time - https://en.wikipedia.org/wiki/Unix_time
    Day of week calculation - https://en.wikipedia.org/wiki/Determ...ay_of_the_week

    Calculating leap year. ( the algorith that i use ) You can find others;
    if((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))
    {
    isleapyear;
    }
    else
    {
    isnotleapyear;
    }

    Videos;
    Thanks and Regards;
    Gadelhas

  11. #11
    Join Date
    Aug 2003
    Location
    Australia
    Posts
    983


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    This sounds like exactly what I did.. an maybe just that I call the code a calendar.
    Except that I have a lookup table of leap years and start the algorithm from the closest to current.
    Actually, thinking again, it might have been dates known to be a Monday on the first day.

  12. #12
    Join Date
    Feb 2013
    Location
    Quebec, Canada
    Posts
    67


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    Quote Originally Posted by johncouture View Post
    ... I am downloading the GMT network time using an ESP8266 ...
    I'm interested. I do you do it? Is-it possible to decode Unix time without using LONG variables?

  13. #13


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    The string comes from the ESP8266 as:

    107 15 Jul 2015 18:57:01 GMT

    The 107 is just a marker indicating that this is a fresh time sync.

    Using arrayread I put everything into byte variables:

    arrayread buffer,[
    dec3 intAction,skip 1,HEX2 GMTDte,skip 1,STR GMTMonth\3,skip 3,
    hex2 GMTYear,skip 1,HEX2 GMTHrs,skip 1,HEX2 GMTMin,skip 1,
    HEX2 GMTSec,skip 1,str GMTTZ\3]

    Then I convert the JUL into a 7 using a FOR loop.

    Finally I call ClockGetLocal which takes the GMT variables and converts them into
    CLK variables. I use word variables for the offset because it needs to handle a
    number up to 1440 (24hrs * 60 minutes). For my "mini-epoch" I again use a
    word variable (60 * 24 * 31 = 44640)

    Now this routine will work for today until the end of the century. I'm 60+ so
    someone else can solve any time issues after that! :-)

    Remember I was just trying to display a clock of HH:MM. In the process I did
    solve the year, month, day of month, hours and minutes. What remains is a
    way to store the time zone ABBV, the offset +/- and dates when they start and
    stop. That will come later when I incorporate the 256K EEPROM.

    Anyway, the secret to it all is that you do not have to put the years and months
    into an epoch. Just solve for the number of minutes since the beginning of the
    month (max size is 44640 and able to fit into a word variable).

    To make a long story short, determine if you went beyond the beginning of the
    month and then make adjustments to the date, the month and the year if
    necessary.

    I tested it with my time zone (- 8 hours) and it works. Again, still to be worked
    out is a way to convert a time zone string into an offset and be able to handle
    plus or minus minutes from GMT.


    '======================================
    ClockGetLocal:
    ' convert GMT variables to Clk variables

    ' =================
    ' FOR TESTING, put GMT past midnight so we can check day calculation
    ' GMTHrs = $01 ' this will cause it to go to previous day
    ' GMTDte = $01 ' 1st of current month so when offset subtracts, it goes to previous month
    ' GMTMon = $03 ' March
    ' GMTYear = $12

    ' first copy GMT into Clk variables that don't change for now
    ClkYear = GMTYear ' for now we ignore changes
    ClkMon = GMTMon ' for now we ignore changes
    ClkSec = GMTSec ' daylight saving time does not affect seconde
    ClkDOW = GMTDOW ' for now we ignore changes

    ' These are hard coded for now
    ClkTemp = 0
    ClkOffset = 420
    ClkTz = "P"
    ClkTZ1 = "D"
    ClkTz2 = "T"
    ClkTz3 = 0
    ClkTz4 = 0

    ' now convert CLK variables to decimal
    ClkYear =((GMTYear >> 4) * 10) + (GMTYear & $0F)
    ClkMon = ((GMTMon >> 4) * 10) + (GMTMon & $0F)
    ClkDte = ((GMTDte >> 4) * 10) + (GMTDte & $0F)
    ClkHrs = ((GMTHrs >> 4) * 10) + (GMTHrs & $0F)
    ClkMin = ((GMTMin >> 4) * 10) + (GMTMin & $0F)

    ' build a mini epoch amount (days, hours and minutes only)
    ClkTemp = 0
    'time_t = time_t + (CLKYear * (minutes at 0 of cur year)
    'time_t = time_t + (CLKMon * (minutes at 0 of cur month)
    ClkTemp = ClkTemp + (ClkDte * 1440) ' add in days (max 46080) (-19455)
    ClkTemp = ClkTemp + ClkMin + (ClkHrs * 60) ' add in hours and minutes

    ' now subtract minutes offset
    ' for now hard code in -7 huors
    'if GMTOffset < 1500 then
    ' time_t = time_t + GMTOffset
    'else
    ' 2s compliment?
    ClkTemp = ClkTemp - ClkOffset
    'endif

    ' adjust for year, month, day

    ' first, is this a leap year?
    if (ClkYear // 4) == 0 then
    ClkDays[2]=29 ' yes, adjust Feb # days
    endif

    ' How many days in mini epoch?
    ClkDte = (ClkTemp / 1440)

    ' After we subtracted the offset
    ' How many days were left in the mini-epoch?
    ' Zero means you crossed midnight
    if ClkDte = 0 then
    ' need to figure out last day of previous month
    ClkMon = ClkMon - 1
    ' if zero, you crossed new year
    if ClkMon = 0 then
    ' you won't have to worry about century
    ClkYear = ClkYear -1
    ClkMon = 12
    endif
    ' Feb was already accounted for above
    ClkDte = ClkDays[ClkMon]
    endif

    ClkHrs = (ClkTemp // 1440) / 60
    ClkMin = ClkTemp // 60

    ' now convert back to BCD
    GMTTemp = ((ClkYear / 10) * 16) + (ClkYear // 10)
    ClkYear = GMTTemp
    GMTTemp = ((ClkMon / 10) * 16) + (ClkMon // 10)
    ClkMon = GMTTemp
    GMTTemp = ((ClkDte / 10) * 16) + (ClkDte // 10)
    ClkDte = GMTTemp
    GMTTemp = ((ClkHrs / 10) * 16) + (ClkHrs // 10)
    ClkHrs = GMTTemp
    GMTTemp = ((ClkMin / 10) * 16) + (ClkMin // 10)
    ClkMin = GMTTemp
    return



    '======================================
    ' CLOCK VARIABLES
    ' Updated:
    ' 08/08/2015 21:24 - JJC clock date/time stored in GMT
    ' Had to adjust for local time
    ' http://www.timeanddate.com/time/dst/
    ' 03/16/2014 15:21 - JJC increased length to 30
    ' 12/18/2012 18:03 - JJC added display mode
    ' 12/16/2012 14:13 - JJC added relay status
    '
    '======================================
    Clock VAR Byte[32] 'Clock Array for clock routines
    ClkCtl var Clock[0] 'Clock Control
    ClkHSec var Clock[1] 'Clock Hundredths Seconds
    ClkSec VAR clock[2] 'Clock Seconds GMT
    ClkMin VAR clock[3] 'Clock Minutes GMT
    ClkHrs VAR clock[4] 'Clock Hours GMT
    ClkDte VAR clock[5] 'Clock Date GMT
    ClkMon VAR clock[6] 'Clock Month GMT
    ClkTmr VAR clock[7] 'Timer Control
    ClkAlm VAR clock[8] 'Alarm Control
    ClkAlmHSec VAR clock[9] 'Alarm Hundredths Seconds
    ClkAlmSec VAR clock[10] 'Alarm Seconds
    ClkAlmMin VAR clock[11] 'Alarm Minutes
    ClkAlmHrs VAR clock[12] 'Alarm Hours
    ClkAlmDte VAR clock[13] 'Alarm Date
    ClkAlmMon VAR clock[14] 'Alarm Month
    ClkAlmYear VAR clock[15] 'Alarm Year
    ClkYear VAR Clock[16] 'Clock Year (last 2 digits) GMT
    ClkDOW var Clock[17] 'Clock Day of the Week GMT
    ClkRelay var Clock[18] 'Relay Status Byte
    ClkMode var Clock[19] 'Clock Display Mode
    ClkTempC var Clock[20] 'Temp in C
    ClkTempF var Clock[21] 'Temp in F
    ClkSavMin var Clock[22] 'Last Transmission Min
    ClkSavHrs var Clock[23] 'Last Transmission Hrs
    ClkSavDte var Clock[24] 'Last Transmission Dte
    ClkTZ var Clock[27]
    ClkTZ1 var Clock[28]
    ClkTZ2 var Clock[29]
    ClkTZ3 var Clock[30]
    ClkTZ4 var Clock[31]

    ClkMonth var byte[3] 'Three character Month like Apr,Jun,Dec
    ClkDays var byte[13] 'Number of days in a month
    Arraywrite ClkDays, [0,31,28,31,30,31,30,31,31,30,31,30,31]
    ClkMonths var byte[52] 'Array of three character months
    arraywrite ClkMonths,[" Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec "]
    ClkOffset var word ' number of minutes from GMT
    ClkTemp var word 'Temporary throwaway value for mini epoch

    GMTClock var byte[32]
    GMTCtl var GMTClock[00] 'Clock Control
    GMTHSec var GMTClock[01] 'Clock Hundredths Seconds
    GMTSec VAR GMTClock[02] 'Clock Seconds GMT
    GMTMin VAR GMTClock[03] 'Clock Minutes GMT
    GMTHrs VAR GMTClock[04] 'Clock Hours GMT
    GMTDte VAR GMTClock[05] 'Clock Date GMT
    GMTMon VAR GMTClock[06] 'Clock Month GMT
    GMTYear var GMTClock[07] 'Clock Year
    GMTDOW var GMTClock[08] 'Clock Day of Week
    GMTTemp var GMTClock[09] ' just needed a calculation byte
    GMTMonth var GMTClock[24] ' leave three bytes
    GMTTZ var GMTClock[27] ' leave five bytes
    GMTTZ1 var GMTClock[28] ' leave five bytes
    GMTTZ2 var GMTClock[29] ' leave five bytes
    GMTTZ3 var GMTClock[30] ' leave five bytes
    GMTTZ4 var GMTClock[31] ' leave five bytes

    ' Other items that need to be stored in EEPROM
    'i2cwrite SDA,SCL,RTC,$00 ' TimeZone ID (5 letters), DST (Y/N),
    ' Offset (leading +/- 1440 minutes)
    'intIPAddr = ""
    'intPortAddr = ""
    'intIPGateway = ""
    'intIPMask = ""
    'intDNS1 = ""
    'intDNS2 = ""
    'strSSID = "router ssid"
    'strPW = "router password"
    'strPVKey = "thingspeak key"
    'strTime = "13 Jul 2015 00:00:00 GMT"
    'your location (city state)
    'your Lat/Long/Elevation
    'zip code to location routine?

    === END OF MESSAGE ===

  14. #14
    Join Date
    Feb 2013
    Location
    Quebec, Canada
    Posts
    67


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    Great! So you are using http://www.timeanddate.com as your time source? At home a setup a HTML page on my Windows Home Server with minimal headers giving me the current datetime but it's not available outside my network. For my lawnmower project I use my cellphone internet sharing because my router is in the basement and I had connections problems. This prevents me from getting the time to my server. That's why is was asking.


    Code:
    <%
    response.write("*" & Format(now, "yyyy-MM-dd HH:mm:ss") & "J")
    
    select case Format(now, "ddd")
    	case "Sun"
    		response.write("1")
    	case "Mon"
    		response.write("2")
    	case "Tue"
    		response.write("3")
    	case "Wed"
    		response.write("4")
    	case "Thu"
    		response.write("5")
    	case "Fri"
    		response.write("6")
    	case "Sat"
    		response.write("7")
    	case else
    		response.write("0")
    end select
    response.write("*" & VbCrLf)
    
    %>
    and the output looks like this:

    Code:
    *2015-08-19 22:33:18J4*
    It's easy to parse and I have DST, date and day number but it's limited to my local network... till I find a free ASP hosting...

    Thanks for sharing!

  15. #15


    Did you find this post helpful? Yes | No

    Default Re: GMT to Local Time Routine

    No, The string comes from the ESP8266 as:

    107 15 Jul 2015 18:57:01 GMT

    The ESP8266 gets it from Google.com

Similar Threads

  1. local exchanges
    By datacomms in forum Ethernet
    Replies: 1
    Last Post: - 28th March 2022, 22:21
  2. Simple "Time-out" routine
    By JacoMuller in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 4th May 2010, 09:16
  3. Internet-Ethernet and Local Net
    By Ioannis in forum General
    Replies: 15
    Last Post: - 7th January 2008, 21:16
  4. local variables
    By BigWumpus in forum PBP Wish List
    Replies: 2
    Last Post: - 10th April 2006, 23:39
  5. RTC 1302 !!! Set time Routine !!
    By uludere72 in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 24th February 2006, 09:28

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts