Using local time with Pico W

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
User avatar
ebolisa
Posts: 55
Joined: Thu Feb 21, 2019 11:43 am
Location: Madrid, Spain

Using local time with Pico W

Post by ebolisa » Sat Jul 16, 2022 12:08 pm

Hi,

I noticed the ntptime lib is not included with the uOS for the Raspberry Pico W version.
Is there a way to get around it to obtain the local time?

TIA

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Using local time with Pico W

Post by pythoncoder » Sat Jul 16, 2022 12:43 pm

Firstly MicroPython doesn't support timezones. However you can get UTC and convert it to local time yourself.

Copy ntptime.py to the Pico W filesystem and use it as follows:

Code: Select all

>>> time.localtime(ntptime.time() + 946702080)
(2022, 7, 16, 17, 25, 50, 5, 197)
Note the factor 946702080 which is 30 year's worth of seconds. This is because the epoch for ESP8266 is 2000 while that for RP2 is 1970.

To correct for TZ just add or subtract N years worth of seconds.
Peter Hinch
Index to my micropython libraries.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Using local time with Pico W

Post by Roberthh » Sat Jul 16, 2022 12:58 pm

You can as well use the ntptime.py referenced by @pythoncoder and change in line 10:

NTP_DELTA = 2208988800 #

and use nptime.settime().

@pythoncoder: I might be wrong, but calculating the difference between 1.1.2000 - 1.1.1970 using LibreOffice Calc returns here 946702080 seconds. And using your code causes an overflow error. Probably you mean:

Code: Select all

time.localtime(ntptime.time() - 946684800)

User avatar
ebolisa
Posts: 55
Joined: Thu Feb 21, 2019 11:43 am
Location: Madrid, Spain

Re: Using local time with Pico W

Post by ebolisa » Sat Jul 16, 2022 1:01 pm

Thank you!

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Using local time with Pico W

Post by pythoncoder » Sun Jul 17, 2022 3:19 pm

Roberthh wrote:
Sat Jul 16, 2022 12:58 pm
...
@pythoncoder: I might be wrong, but calculating the difference between 1.1.2000 - 1.1.1970 using LibreOffice Calc returns here 946702080 seconds. And using your code causes an overflow error. Probably you mean:

Code: Select all

time.localtime(ntptime.time() - 946684800)
I realised in the early hours of this morning that I'd got my sums wrong: the number should indeed be 946684800.

But I do think addition is correct. The NTP query returns seconds from 1900 to now, and the library subtracts an offset to shift the datum to 2000. This offset is too large if our epoch is to be 1970 so we need to add an offset. This is borne out by the following on my Pico W which is cut and pasted verbatim:

Code: Select all

>>> time.localtime(ntptime.time() + 946684800)
(2022, 7, 17, 14, 58, 43, 6, 198)
Subtraction produces a ridiculous result from the start of the swinging sixties ;)
Peter Hinch
Index to my micropython libraries.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Using local time with Pico W

Post by Roberthh » Sun Jul 17, 2022 4:35 pm

You're right. Using the ntptime.py from the esp8266 port, one has to add 946684800.
Besides that, I changed the module into NTP_DELTA = 2208988800, which is the seconds difference between 1.1.1970 and 1.1.1900.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Using local time with Pico W

Post by pythoncoder » Mon Jul 18, 2022 12:37 pm

Here is a version of ntptime.py which is platform-independent. Tested on Unix, ESP8266, Pico W. It also allows for a local time offset. Hopefully it will be of use to someone ;)

Code: Select all

import socket
import struct
from time import gmtime

# (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
# (date(1970, 1, 1) - date(1900, 1, 1)).days * 24*60*60
NTP_DELTA = 3155673600 if gmtime(0)[0] == 2000 else 2208988800

# The NTP host can be configured at runtime by doing: ntptime.host = 'myhost.org'
host = "pool.ntp.org"

def time(hrs_offset=0):  # Local time offset in hrs relative to UTC
    NTP_QUERY = bytearray(48)
    NTP_QUERY[0] = 0x1B
    addr = socket.getaddrinfo(host, 123)[0][-1]
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.settimeout(1)
        res = s.sendto(NTP_QUERY, addr)
        msg = s.recv(48)
    finally:
        s.close()
    val = struct.unpack("!I", msg[40:44])[0]
    return val - NTP_DELTA + hrs_offset * 3600
Sadly a platform-independent way of setting the RTC will have to wait for a portable RTC class :(
Peter Hinch
Index to my micropython libraries.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Using local time with Pico W

Post by pythoncoder » Wed Jul 27, 2022 10:00 am

Updated version here. This adds portability by using select.poll rather than deprecated socket timeouts (see docs).
Peter Hinch
Index to my micropython libraries.

Jibun no kage
Posts: 144
Joined: Mon Jul 25, 2022 9:45 pm

Re: Using local time with Pico W

Post by Jibun no kage » Wed Jul 27, 2022 1:34 pm

@Peter, where is the example? Of how to use select.poll? Oh... the 'here' is link. Missed that!

p_j
Posts: 102
Joined: Mon Aug 23, 2021 1:08 pm
Location: Sydney

Re: Using local time with Pico W

Post by p_j » Wed Jul 27, 2022 2:24 pm

I haven't tested it out but I believe datetime with tz support was added to micropython-lib a few months ago?

https://github.com/micropython/micropyt ... b/datetime

Post Reply