time --- ฟังก์ชันเกี่ยวกับเวลา

โมดูล time ให้ฟังก์ชันสำหรับรับเวลาและวันที่ปัจจุบัน การวัดช่วงเวลา และการหน่วงเวลา

Time Epoch: OpenMV Cam ที่ใช้ Alif และ i.MX RT ใช้ POSIX epoch ของ 1970-01-01 00:00:00 UTC ส่วน OpenMV Cam ที่ใช้ STM32 ใช้ epoch ของ 2000-01-01 00:00:00 UTC ปีของ epoch สามารถกำหนดได้ที่ runtime ด้วย gmtime(0)[0]

การรักษาวันที่/เวลาตามปฏิทินจริง: สิ่งนี้ต้องการ Real Time Clock (RTC) บน OpenMV Cam เวลาของระบบให้บริการโดยออบเจกต์ machine.RTC เวลาตามปฏิทินปัจจุบันอาจถูกตั้งด้วย machine.RTC().datetime(tuple) และได้รับการรักษาโดยหนึ่งใน:

  • แบตเตอรี่สำรอง (ส่วนประกอบเสริมบน OpenMV Cam บางรุ่น)

  • โปรโตคอลเวลาผ่านเครือข่าย เช่น ntptime (ต้องการการเชื่อมต่อเครือข่าย)

  • การตั้งค่าด้วยตนเองในแต่ละครั้งที่เปิดเครื่อง RTC จะถูกรักษาไว้ตลอดการรีเซ็ตแบบ soft โดยปกติ แต่จะสูญหายเมื่อไฟดับ ยกเว้นมีแบตเตอรี่สำรอง

หากไม่ได้รักษาเวลาตามปฏิทิน ฟังก์ชันด้านล่างที่อ้างอิงเวลาสัมบูรณ์ปัจจุบันจะไม่ทำงานตามที่คาดหวัง

ฟังก์ชัน

time.gmtime(secs: int | None = None) Tuple[int, int, int, int, int, int, int, int]
time.localtime(secs: int | None = None) Tuple[int, int, int, int, int, int, int, int]

แปลงเวลา secs ที่แสดงในหน่วยวินาทีนับจาก Epoch (ดูด้านบน) ให้เป็นทูเพิล 8 ตัวที่ประกอบด้วย: (year, month, mday, hour, minute, second, weekday, yearday) ถ้า secs ไม่ได้ระบุหรือเป็น None ระบบจะใช้เวลาปัจจุบันจาก RTC

ฟังก์ชัน gmtime() คืนค่าทูเพิลวันที่-เวลาใน UTC และ localtime() คืนค่าทูเพิลวันที่-เวลาตามเวลาท้องถิ่น

รูปแบบของรายการในทูเพิล 8 ตัวได้แก่:

  • year รวมศตวรรษ (ตัวอย่างเช่น 2014)

  • month เป็น 1-12

  • mday เป็น 1-31

  • hour เป็น 0-23

  • minute เป็น 0-59

  • second เป็น 0-59

  • weekday เป็น 0-6 สำหรับ จันทร์-อาทิตย์

  • yearday เป็น 1-366

time.mktime(date_time_tuple: Tuple[int, int, int, int, int, int, int, int]) int

นี่คือฟังก์ชันผกผันของ localtime โดยรับอาร์กิวเมนต์เป็นทูเพิล 8 ตัวเต็มที่แสดงเวลาตามรูปแบบ localtime แล้วคืนค่าจำนวนเต็มซึ่งเป็นจำนวนวินาทีนับตั้งแต่ time epoch

time.sleep(seconds: float) None

หน่วงเวลาตามจำนวนวินาทีที่กำหนด seconds อาจเป็นเลขทศนิยมเพื่อหน่วงเวลาเป็นเศษส่วนของวินาที สำหรับการหน่วงเวลาที่ละเอียดกว่าหรือแบบจำนวนเต็มเท่านั้น ใช้ฟังก์ชัน sleep_ms() และ sleep_us()

การเรียก sleep() รวมถึง sleep(0) รับประกันว่าจะเรียกฟังก์ชัน callback ที่รอดำเนินการ

time.sleep_ms(ms: int) None

หน่วงเวลาตามจำนวนมิลลิวินาทีที่กำหนด ควรเป็นบวกหรือ 0

ฟังก์ชันนี้จะหน่วงเวลาอย่างน้อยตามจำนวนมิลลิวินาทีที่กำหนด แต่อาจใช้เวลานานกว่านั้นหากต้องมีการประมวลผลอื่น เช่น interrupt handlers หรือ thread อื่น การส่ง 0 สำหรับ ms ยังคงอนุญาตให้การประมวลผลอื่นนี้เกิดขึ้น ใช้ sleep_us() สำหรับการหน่วงเวลาที่แม่นยำกว่า

การเรียก sleep_ms() รวมถึง sleep_ms(0) รับประกันว่าจะเรียกฟังก์ชัน callback ที่รอดำเนินการ

time.sleep_us(us: int) None

หน่วงเวลาตามจำนวนไมโครวินาทีที่กำหนด ควรเป็นบวกหรือ 0

ฟังก์ชันนี้พยายามให้การหน่วงเวลาที่แม่นยำอย่างน้อย us ไมโครวินาที แต่อาจใช้เวลานานกว่าหากระบบมีการประมวลผลที่มีความสำคัญสูงกว่าที่ต้องดำเนินการ

time.ticks_ms() int

คืนค่าตัวนับมิลลิวินาทีที่เพิ่มขึ้นพร้อมจุดอ้างอิงที่กำหนดเองซึ่งจะวนซ้ำหลังจากค่าหนึ่ง

ค่าที่ wrap-around ไม่ได้เปิดเผยอย่างชัดเจน แต่เราจะเรียกมันว่า TICKS_MAX เพื่อความสะดวกในการอธิบาย ช่วงของค่าคือ TICKS_PERIOD = TICKS_MAX + 1 TICKS_PERIOD รับประกันว่าเป็นเลขยกกำลังสอง แต่อาจแตกต่างกันในแต่ละพอร์ต ค่าช่วงเดียวกันนี้ใช้สำหรับฟังก์ชัน ticks_ms(), ticks_us(), ticks_cpu() ทั้งหมด (เพื่อความเรียบง่าย) ดังนั้น ฟังก์ชันเหล่านี้จะคืนค่าในช่วง [0 .. TICKS_MAX] รวม ทั้งหมด TICKS_PERIOD ค่า โปรดทราบว่าใช้เฉพาะค่าที่ไม่ใช่ลบ ส่วนใหญ่แล้ว คุณควรปฏิบัติต่อค่าที่ส่งคืนโดยฟังก์ชันเหล่านี้เหมือนเป็น opaque การดำเนินการเดียวที่มีให้สำหรับพวกมันคือฟังก์ชัน ticks_diff() และ ticks_add() ที่อธิบายด้านล่าง

หมายเหตุ: การดำเนินการทางคณิตศาสตร์มาตรฐาน (+, -) หรือตัวดำเนินการเปรียบเทียบ (<, <=, >, >=) โดยตรงกับค่าเหล่านี้จะนำไปสู่ผลลัพธ์ที่ไม่ถูกต้อง การดำเนินการทางคณิตศาสตร์แล้วส่งผลลัพธ์เป็นอาร์กิวเมนต์ให้กับ ticks_diff() หรือ ticks_add() ก็จะนำไปสู่ผลลัพธ์ที่ไม่ถูกต้องจากฟังก์ชันหลัง

time.ticks_us() int

เหมือนกับ ticks_ms() ด้านบน แต่เป็นหน่วยไมโครวินาที

time.ticks_cpu() int

คล้ายกับ ticks_ms() และ ticks_us() แต่มีความละเอียดสูงสุดที่เป็นไปได้ในระบบ โดยทั่วไปจะเป็นสัญญาณนาฬิกา CPU ซึ่งเป็นที่มาของชื่อฟังก์ชัน แต่ไม่จำเป็นต้องเป็น CPU clock ก็ได้ อาจใช้แหล่งกำหนดเวลาอื่นที่มีในระบบ (เช่น high-resolution timer) แทนได้ หน่วยเวลาที่แน่นอน (ความละเอียด) ของฟังก์ชันนี้ไม่ได้ระบุในระดับโมดูล time แต่เอกสารสำหรับพอร์ตเฉพาะอาจให้ข้อมูลที่ละเอียดกว่า ฟังก์ชันนี้มีไว้สำหรับการวัดประสิทธิภาพที่ละเอียดมากหรือ real-time loops ที่แน่นหนา หลีกเลี่ยงการใช้ในโค้ดที่พกพาได้ มีให้บน OpenMV Cam ทุกรุ่น

time.ticks_add(ticks: int, delta: int) int

เพิ่มค่า ticks ด้วยจำนวนที่กำหนด ซึ่งอาจเป็นบวกหรือลบก็ได้ เมื่อให้ค่า ticks ฟังก์ชันนี้ช่วยคำนวณค่า ticks delta ticks ก่อนหรือหลังจากมัน ตามนิยาม modular-arithmetic ของค่า tick (ดู ticks_ms() ด้านบน) พารามิเตอร์ ticks ต้องเป็นผลโดยตรงจากการเรียก ticks_ms(), ticks_us() หรือ ticks_cpu() (หรือจากการเรียก ticks_add() ก่อนหน้า) อย่างไรก็ตาม delta อาจเป็นจำนวนเต็มหรือนิพจน์ตัวเลขใดก็ได้ ticks_add() มีประโยชน์สำหรับการคำนวณ deadline สำหรับเหตุการณ์/งาน (หมายเหตุ: คุณต้องใช้ฟังก์ชัน ticks_diff() เพื่อทำงานกับ deadline)

ตัวอย่าง:

# Find out what ticks value there was 100ms ago
print(ticks_add(time.ticks_ms(), -100))

# Calculate deadline for operation and test for it
deadline = ticks_add(time.ticks_ms(), 200)
while ticks_diff(deadline, time.ticks_ms()) > 0:
    do_a_little_of_something()

# Find out TICKS_MAX used by this port
print(ticks_add(0, -1))
time.ticks_diff(ticks1: int, ticks2: int) int

วัดความต่างของ ticks ระหว่างค่าที่ส่งคืนจากฟังก์ชัน ticks_ms(), ticks_us() หรือ ticks_cpu() เป็นค่าที่มีเครื่องหมายซึ่งอาจ wrap around ได้

ลำดับอาร์กิวเมนต์เหมือนกับตัวดำเนินการลบ ticks_diff(ticks1, ticks2) มีความหมายเดียวกับ ticks1 - ticks2 อย่างไรก็ตาม ค่าที่ส่งคืนโดย ticks_ms() เป็นต้น อาจ wrap around ดังนั้นการใช้การลบโดยตรงกับพวกมันจะให้ผลลัพธ์ที่ไม่ถูกต้อง นั่นคือเหตุผลที่ต้องการ ticks_diff() ซึ่งใช้ modular (หรือเฉพาะเจาะจงกว่าคือ ring) arithmetic เพื่อให้ผลลัพธ์ที่ถูกต้องแม้สำหรับค่า wrap-around (ตราบใดที่พวกมันไม่ห่างกันมากเกินไป ดูด้านล่าง) ฟังก์ชันคืนค่า ที่มีเครื่องหมาย ในช่วง [-TICKS_PERIOD/2 .. TICKS_PERIOD/2-1] (นั่นคือนิยามช่วงทั่วไปสำหรับจำนวนเต็มไบนารีที่มีเครื่องหมายแบบ two's-complement) ถ้าผลลัพธ์เป็นลบ แสดงว่า ticks1 เกิดขึ้นก่อน ticks2 มิฉะนั้น แสดงว่า ticks1 เกิดขึ้นหลัง ticks2 สิ่งนี้ถือว่า ถูกต้องก็ต่อเมื่อ ticks1 และ ticks2 อยู่ห่างกันไม่เกิน TICKS_PERIOD/2-1 ticks หากเงื่อนไขนั้นไม่เป็นจริง ผลลัพธ์ที่ไม่ถูกต้องจะถูกส่งคืน โดยเฉพาะอย่างยิ่ง หากค่า tick สองค่าอยู่ห่างกัน TICKS_PERIOD/2-1 ticks ค่านั้นจะถูกส่งคืนโดยฟังก์ชัน อย่างไรก็ตาม หาก TICKS_PERIOD/2 ของ tick เวลาจริงได้ผ่านไปแล้ว ฟังก์ชันจะคืนค่า -TICKS_PERIOD/2 แทน กล่าวคือ ค่าผลลัพธ์จะ wrap around ไปยังช่วงค่าลบที่เป็นไปได้

เหตุผลที่ไม่เป็นทางการของข้อจำกัดข้างต้น: สมมติว่าคุณถูกขังอยู่ในห้องโดยไม่มีวิธีติดตามการผ่านของเวลา ยกเว้นนาฬิกาแบบมาตรฐาน 12 รอยบาก จากนั้น ถ้าคุณมองหน้าปัดตอนนี้ และไม่มองอีกเป็นเวลา 13 ชั่วโมง (เช่น ถ้าคุณหลับนานมาก) แล้วเมื่อคุณมองอีกครั้ง อาจดูเหมือนว่าผ่านไปเพียง 1 ชั่วโมง เพื่อหลีกเลี่ยงข้อผิดพลาดนี้ ให้มองนาฬิกาสม่ำเสมอ แอปพลิเคชันของคุณควรทำเช่นเดียวกัน อุปมา "หลับนานเกินไป" ยังตรงกับพฤติกรรมของแอปพลิเคชันโดยตรง: อย่าให้แอปพลิเคชันของคุณทำงานเดียวนานเกินไป รันงานเป็นขั้นตอน และติดตามเวลาระหว่างนั้น

ticks_diff() ถูกออกแบบมาเพื่อรองรับรูปแบบการใช้งานที่หลากหลาย รวมถึง:

  • การ polling พร้อม timeout ในกรณีนี้ ลำดับของเหตุการณ์เป็นที่ทราบ และคุณจะจัดการเฉพาะผลลัพธ์บวกของ ticks_diff()

    # Wait for GPIO pin to be asserted, but at most 500us
    start = time.ticks_us()
    while pin.value() == 0:
        if time.ticks_diff(time.ticks_us(), start) > 500:
            raise TimeoutError
    
  • การกำหนดเวลาเหตุการณ์ ในกรณีนี้ ผลลัพธ์ของ ticks_diff() อาจเป็นลบหากเหตุการณ์เกินกำหนด:

    # This code snippet is not optimized
    now = time.ticks_ms()
    scheduled_time = task.scheduled_time()
    if ticks_diff(scheduled_time, now) > 0:
        print("Too early, let's nap")
        sleep_ms(ticks_diff(scheduled_time, now))
        task.run()
    elif ticks_diff(scheduled_time, now) == 0:
        print("Right at time!")
        task.run()
    elif ticks_diff(scheduled_time, now) < 0:
        print("Oops, running late, tell task to run faster!")
        task.run(run_faster=true)
    

หมายเหตุ: อย่าส่งค่า time() ไปยัง ticks_diff() คุณควรใช้การดำเนินการทางคณิตศาสตร์ปกติกับพวกมัน แต่โปรดทราบว่า time() อาจ (และจะ) overflow ด้วย ซึ่งเป็นที่รู้จักในชื่อ https://en.wikipedia.org/wiki/Year_2038_problem

time.time() int

คืนค่าจำนวนวินาที เป็นจำนวนเต็ม นับตั้งแต่ Epoch โดยสมมติว่า RTC พื้นฐานได้รับการตั้งค่าและรักษาไว้ตามที่อธิบายข้างต้น หาก RTC ไม่ได้ถูกตั้งค่า ฟังก์ชันนี้จะคืนค่าจำนวนวินาทีนับตั้งแต่จุดอ้างอิงเฉพาะพอร์ต (สำหรับบอร์ด embedded ที่ไม่มี RTC สำรองแบตเตอรี่ โดยปกติจะนับตั้งแต่เปิดเครื่องหรือรีเซ็ต) หากต้องการพัฒนาแอปพลิเคชัน MicroPython ที่พกพาได้ คุณไม่ควรพึ่งพาฟังก์ชันนี้เพื่อให้ความแม่นยำสูงกว่าหนึ่งวินาที หากต้องการความแม่นยำสูงกว่า absolute timestamps ให้ใช้ time_ns() หากเวลาสัมพัทธ์เป็นที่ยอมรับได้ ให้ใช้ฟังก์ชัน ticks_ms() และ ticks_us() หากต้องการเวลาตามปฏิทิน gmtime() หรือ localtime() โดยไม่มีอาร์กิวเมนต์เป็นตัวเลือกที่ดีกว่า

ความแตกต่างจาก CPython

ใน CPython ฟังก์ชันนี้คืนค่าจำนวนวินาทีนับตั้งแต่ Unix epoch (1970-01-01 00:00 UTC) เป็นค่าทศนิยม โดยปกติมีความแม่นยำระดับไมโครวินาที บน OpenMV Cam มันคืนค่า จำนวนเต็ม ที่มีความแม่นยำหนึ่งวินาที -- ฮาร์ดแวร์ไม่สามารถแทนทั้งช่วงเวลายาวและความแม่นยำต่ำกว่าวินาทีในเลขทศนิยมได้ -- และ epoch แตกต่างกันตามบอร์ด (ดู Time Epoch ด้านบน) หากไม่มี RTC สำรองแบตเตอรี่ที่ได้รับการตั้งค่า มันจะนับวินาทีนับตั้งแต่เปิดเครื่อง/รีเซ็ตแทน

time.time_ns() int

คล้ายกับ time() แต่คืนค่านาโนวินาทีนับตั้งแต่ Epoch เป็นจำนวนเต็ม (โดยปกติเป็น big integer ดังนั้นจะจัดสรรบน heap)

Constructors

class time.clock

คืนค่าออบเจกต์ clock

Methods

tick() None

เริ่มติดตามเวลาที่ผ่านไป

fps() float

หยุดติดตามเวลาที่ผ่านไปและคืนค่า FPS ปัจจุบัน (เฟรมต่อวินาที)

เรียก tick ก่อนเสมอก่อนที่จะเรียกฟังก์ชันนี้

avg() float

หยุดติดตามเวลาที่ผ่านไปและคืนค่าเวลาเฉลี่ยที่ผ่านไปในหน่วยมิลลิวินาที

เรียก tick ก่อนเสมอก่อนที่จะเรียกฟังก์ชันนี้

reset() None

รีเซ็ตออบเจกต์ clock