logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[STM32][Newlib] time.h strefy czasowe i czas letni/zimowy

kriss68 10 Paź 2011 19:13 4387 15
REKLAMA
  • #1 10013246
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    Witam.

    Jak ustawić strefę czasową i czas letni/zimowy? Biblioteka newlib wszystko ładnie przelicza tylko jak sprawić by uwzględniała strefę czasową? Niby jest od tego funkcja tzset(); która powinna to ustawić tylko, że jest to funkcja bezparametrowa. I tu pytanie jak to ustawić? Próbowałem też zmienić zmienną środowiskową TZ tylko nawet nie wiem czy ona istnieje skoro nie mam żadnego os. Teoretycznie funkcja putenv("TZ=std 3600"); powinna to zrobić. TZ gdy nie ma czasu letniego/zimowego powinna wyglądać tak: "std offset" tylko, że to wszystko jest dla systemów unixowych a ja żadnego systemu nie mam. Czy da się to w ogóle zrobić czy też muszę napisać swój własny kalendarz uwzględniający strefę czasową i czas letni/zimowy? Dodam tylko, że kompilator mi nic nie wysypuje na tych dwóch funkcjach a czas który dostaje cały czas jest bez uwzględnienia strefy czasowej.
  • REKLAMA
  • #2 10370035
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    Problem rozwiązany :)
    "Wystarczy" stworzyć na początku takie oto dwie zmienne:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    time_zone ma wartość odpowiednią dla polski. Jeśli będą chętni to wyjaśnię co robią poszczególne "znaczki".
    Po tym zabiegu na początku main dajemy takie coś:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    I teraz funkcja
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Po podaniu jako tim liczby sekund od 1 stycznia 1970 zwróci nam wskaźnik na piękną strukturę typu tm w której pola będą wypełnione z uwzględnieniem lat przestępnych, strefy czasowej oraz czasu letniego i zimowego.

    Oczywiście należy pamiętać o #include <time.h> :D

    Testowałem to w TrueStudio jeśli komuś to zadziała z innym kompilatorem (wielce prawdopodobne) to proszę o podzielenie się odpowiednia informacją :)
  • REKLAMA
  • #3 10471886
    m.ki
    Poziom 15  
    Posty: 117
    Pomógł: 13
    kriss68 napisał:
    Testowałem to w TrueStudio jeśli komuś to zadziała z innym kompilatorem (wielce prawdopodobne) to proszę o podzielenie się odpowiednia informacją :)


    Niestety, w CooCox nie zadziałało - nie znalazł zmiennej __env. Ale Twój post mnie ukierunkował na poszukiwania - to samo można zrobić bardziej uniwersalnie:

    Na początku:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    A w kodzie na początku main.c:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    A dalej, jak u Ciebie.
    Pozdrowienia,
    m.ki
  • REKLAMA
  • #4 10478262
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    Potwierdzam, w TrueStudio takie coś też działa, nawet nie pomyślałem o tym, że setenv() będzie działać na "zwykłych" procesorkach. Ale dziwne, że CooCox nie znalazł takiej nazwy bo wytargałem ja ze źródeł newliba, czyżby on używał jakiejś innej kompilacji tej biblioteki?
  • #5 10481219
    m.ki
    Poziom 15  
    Posty: 117
    Pomógł: 13
    kriss68 napisał:
    Ale dziwne, że CooCox nie znalazł takiej nazwy bo wytargałem ja ze źródeł newliba, czyżby on używał jakiejś innej kompilacji tej biblioteki?

    Też mnie to zaciekawiło i zacząłem grzebać w źródłach newliba. Faktycznie, __env jest, ale w części związanej z RDOS - zapewne w CooCox tego nie dokompilowali.
    (Zresztą, __env jest tam utożsamione z environ, czyli zmienną wskazującą na zmienne środowiska wg definicji Posix. W CooCox environ jest odnajdywana).

    Pozdrowienia,
    MKi
  • #6 10481607
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    U mnie environ jest wskaźnikiem na __env. Odwołuje też, że sposób z setenv() działa w TrueStudio okazało się, że po kolejnym wgraniu rogramu już źle pokazuje godzinę, wróciłem do mojego rozwiązania ;)
  • #7 11119558
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Wszystko pięknie, tylko wykorzystanie zmiennych środowiskowych "kosztuje" u mnie jakieś 32kB kodu i trochę ponad 1kB RAM (+ zapewne jeszcze dynamiczna alokacja), więc chyba sobie daruję strefy czasowe <:

    Analiza na szybko każe mi sądzić, że przyrost związany jest z funkcją scanf() (czy jakimś jej wariantem).

    4\/3!!
  • #8 11119957
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    Freddie rozumiem, ze korzystasz z gcc i nieużywane sekcje wyrzuciłeś? Ja to rozwiązanie stosowałem jeszcze z TrueStudio i poza zwiększeniem rozmiaru o tego stringa nic mi nie "urosło" ;] No chyba, ze sposób kolegi m.ki coś tam zmienia, ja jak to rozgryźć doszedłem analizując źródła stdlib i po drodze nie natrafiłem na żadne dynamiczne alokowanie pamięci. Porównujesz rozmiary tylko z lub bez zmiennej środowiskowej czy z lub bez całego time.h? Bo tu mogą te bajty uciekać ;]
  • #9 11120276
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    kriss68 napisał:
    Freddie rozumiem, ze korzystasz z gcc i nieużywane sekcje wyrzuciłeś?

    No raczej (;

    kriss68 napisał:
    Ja to rozwiązanie stosowałem jeszcze z TrueStudio i poza zwiększeniem rozmiaru o tego stringa nic mi nie "urosło" ;]

    Musiało Ci coś brakować do pełnego działania programu (; W końcu analiza takiego zakręconego stringa nie jest do zrobienia w 2 linijkach (chyba że obydwie to scanf() )...

    kriss68 napisał:
    Porównujesz rozmiary tylko z lub bez zmiennej środowiskowej czy z lub bez całego time.h? Bo tu mogą te bajty uciekać ;]

    Porównuję sytuację w której w programie jest wywołanie funkcji setenv() z brakiem takiego wywołania.

    kriss68 napisał:
    po drodze nie natrafiłem na żadne dynamiczne alokowanie pamięci.

    W kodzie który zostaje u mnie wciągnięty jest pełno odwołań do malloc(), więc...

    4\/3!!
  • #10 11121296
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    A widzisz, różnica jest taka, że u mnie nie jest wywoływane setenv() tylko bezpośrednio przypisuje ten łańcuch do wskaźnika.
  • REKLAMA
  • #11 11121434
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Efekt taki sam... Przed:
       text	   data	    bss	    dec	    hex	filename
      79288	   2244	  40256	 121788	  1dbbc	out/....elf

    Po dodaniu do main() jednej linijki z wywołaniem tzset():

       text	   data	    bss	    dec	    hex	filename
     105068	   2392	  40540	 148000	  24220	out/....elf


    Powód jest generalnie ten sam - scanf(). Tutaj jest kod newlibowego _tzset_r():

    http://sourceware.org/cgi-bin/cvsweb.cgi/src/...ent-type=text/x-cvsweb-markup&cvsroot=src

    if (sscanf (tzenv, "%10[^0-9,+-]%n", __tzname_std, &n) <= 0)
    ...
    if (sscanf (tzenv, "%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n) < 1)
    ...
    if (sscanf (tzenv, "%10[^0-9,+-]%n", __tzname_dst, &n) <= 0)

    itd. jeszcze kilka razy

    Jeśli nie zauważałeś takiego przyrostu u siebie, to powody mogą być wg mnie trzy:
    1. TrueStudio ma swoją bibliotekę do scanf(), który jest wtedy drastycznie mniejszy
    2. Masz swoje własne - mniejsze - scanf()
    3. W projekcie i tak gdzieś używałeś scanf(), więc dodanie stref czasowych nie musiało dociągnąć 30kB kodu tylko np 2kB (bo 28kB już było i tak).

    4\/3!!
  • #12 11123430
    m.ki
    Poziom 15  
    Posty: 117
    Pomógł: 13
    kriss68 napisał:
    No chyba, ze sposób kolegi m.ki coś tam zmienia...

    Nic nie zmienia, też mam ponad 30KB+ (CooCox). Ale ja mam jeszcze daleko do sufitu w moich zastosowaniach.
    Co nie zmienia faktu, że jak się ktoś zaofiaruje z innym rozwiązaniem, to chętnie skorzystam.

    Przy okazji, w zasadzie zagadnienie nie związane z programowaniem, tylko właśnie ze zmianą czasu letni/zimowy.
    Jak zareagować, gdy użytkownik zmieni czas na 2:30 w dniu, gdy jest przejście z letniego na zimowy? Ustawić letni, czy zimowy? Jasne, problem raczej akademicki, komu by się chciało w nocy, ale coś trzeba ustalić. Ja wymyśliłem, że zostawiam poprzednie ustawienie (był letni, zostaje letni). A może to jest jakoś unormowane?

    Pozdrowienia,
    m.ki
  • #13 11123783
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    Zmiana czasu w Polsce następuje w konkretnej sekundzie więc nie widzę problemu, jest to bodajże 1:00 czasu UTC. Co do rozwiązania to czas letni/zimowy łatwo wyliczyć, jedyną trudnością jest brak stałości tych dat bo są to ostatnie niedziele miesiąca.
  • #14 11135620
    m.ki
    Poziom 15  
    Posty: 117
    Pomógł: 13
    kriss68 napisał:
    Zmiana czasu w Polsce następuje w konkretnej sekundzie więc nie widzę problemu, jest to bodajże 1:00 czasu UTC. Co do rozwiązania to czas letni/zimowy łatwo wyliczyć, jedyną trudnością jest brak stałości tych dat bo są to ostatnie niedziele miesiąca.


    Widzisz, problem leży w tym że w dniu zmiany letni -> zimowy mamy dwie godziny 2:30 (czasu lokalnego) - pierwszą w czasie letnim, a po półgodzinie o 3:00 czasu letniego następuje cofnięcie do 2:00 czasu zimowego i po kolejnej półgodzinie mamy 2:30 czasu zimowego. Te sam problem dotyczy oczywiście każdej chwili w ciągu tej "zdublowanej godziny".
    Dla Polski pierwsza 2:30 to 0:30 UTC, a druga to 1:30 UTC. (UTC to to samo, co GMT?)
    Żeby było zabawniej, w dniu zmiany zimowy -> letni nie ma w ogóle godziny 2:30.

    Pozdrowienia,
    MKi
  • #15 11135688
    kriss68
    Poziom 20  
    Posty: 369
    Pomógł: 40
    Ocena: 37
    No ok ale ja dalej nie widzę problemu - w RTC przechowujesz czas UTC, przy zmianie czasu też musisz najpierw prze konwertować do UTC więc zawsze można wywalić jakiś błąd gdy nie może istnieć taka godzina(np wspomniana 2:30) a gdy taka godzina istnieje 2x - też 2:30 to uznać, ze jest ona podana w czasie UTC+1 (tzn po cofnięciu o 1h).
  • #16 11136587
    m.ki
    Poziom 15  
    Posty: 117
    Pomógł: 13
    kriss68 napisał:
    (...) zawsze można wywalić jakiś błąd gdy nie może istnieć taka godzina(np wspomniana 2:30) a gdy taka godzina istnieje 2x - też 2:30 to uznać, ze jest ona podana w czasie UTC+1 (tzn po cofnięciu o 1h).


    No i na tym dokładnie polega mój problem.
    Jakoś nie wyobrażam sobie wyświetlenia użytkownikowi komunikatu "nie ma takiej godziny". Znasz jakiś zegar, który tak robi? Muszę (tj. program musi) coś przedsięwziąć - np. jak godziny nie ma, to skoczyć do najbliżej (a może skoczyć o godzinę do przodu?), jak jest podwójna - ustawić wg czasu zimowego. Albo letniego. Albo tego, który był ostatnio.

    Pozdrowienia,
    m.ki

Podsumowanie tematu

✨ Użytkownicy dyskutują o ustawieniu strefy czasowej oraz czasu letniego/zimowego w kontekście użycia biblioteki Newlib w systemach opartych na STM32. Główne rozwiązanie polega na zdefiniowaniu zmiennej środowiskowej TZ oraz użyciu funkcji tzset(). Użytkownicy dzielą się różnymi podejściami, w tym użyciem setenv() do ustawienia strefy czasowej. Wskazują również na problemy z różnymi kompilatorami, takimi jak TrueStudio i CooCox, oraz na różnice w implementacji zmiennych środowiskowych. Dodatkowo, poruszają kwestie związane z obsługą podwójnych godzin podczas zmiany czasu letniego na czas zimowy, proponując różne metody radzenia sobie z tym problemem.
Wygenerowane przez model językowy.
REKLAMA