Konvertiert unix timestamp in Datum ohne system-libs
Baue ich ein embedded Projekt, das zeigt die Zeit, abgerufen von einem GPS-Modul auf einem display, aber ich möchte auch die Anzeige des aktuellen Datums. Ich habe momentan die Zeit als unix-Zeitstempel und die progject ist in C geschrieben.
Ich bin auf der Suche nach einer Möglichkeit zum berechnen der aktuellen UTC-Datum aus dem Zeitstempel, wobei die Schaltjahre berücksichtigt? Denken Sie daran, dies ist für ein embedded Projekt, bei dem es keine FPU, also floating point math emuliert wird, vermeiden Sie so viel wie möglich für die Leistung erforderlich ist.
BEARBEITEN
Nach einem Blick auf @R...'s code, habe ich beschlossen, ein gehen, ein schreiben das ich und kam mit der folgenden.
void calcDate(struct tm *tm)
{
uint32_t seconds, minutes, hours, days, year, month;
uint32_t dayOfWeek;
seconds = gpsGetEpoch();
/* calculate minutes */
minutes = seconds / 60;
seconds -= minutes * 60;
/* calculate hours */
hours = minutes / 60;
minutes -= hours * 60;
/* calculate days */
days = hours / 24;
hours -= days * 24;
/* Unix time starts in 1970 on a Thursday */
year = 1970;
dayOfWeek = 4;
while(1)
{
bool leapYear = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
uint16_t daysInYear = leapYear ? 366 : 365;
if (days >= daysInYear)
{
dayOfWeek += leapYear ? 2 : 1;
days -= daysInYear;
if (dayOfWeek >= 7)
dayOfWeek -= 7;
++year;
}
else
{
tm->tm_yday = days;
dayOfWeek += days;
dayOfWeek %= 7;
/* calculate the month and day */
static const uint8_t daysInMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
for(month = 0; month < 12; ++month)
{
uint8_t dim = daysInMonth[month];
/* add a day to feburary if this is a leap year */
if (month == 1 && leapYear)
++dim;
if (days >= dim)
days -= dim;
else
break;
}
break;
}
}
tm->tm_sec = seconds;
tm->tm_min = minutes;
tm->tm_hour = hours;
tm->tm_mday = days + 1;
tm->tm_mon = month;
tm->tm_year = year;
tm->tm_wday = dayOfWeek;
}
Nur wenn die Abwesenheit Ihrer Berechnung werden die zu einer großen Marge von Fehler (was ich bezweifle).
UTC und GPS-Zeit sind 16 Sekunden anders jetzt durch Schaltsekunden. Dies wird nicht variieren schnell. In anderen Worten, wenn Sie nur die Anzeige des aktuellen Datum, können Sie Sie ignorieren Schaltsekunden.
Wenn die Epoche, in der Zeit ist abgeleitet aus dem GPS-Modul, es wird wahrscheinlich Schaltsekunden entfielen - GPS-überträgt die Differenz zwischen GPS-und UTC-Zeit jeden 13.5 Minuten, die standard-NMEA0183-RMC-Satz die Zeit ist definiert als UTC-Zeit, nicht der GPS-Zeit, das Modul soll den offset vor der Ausgabe. GLONASS (Russisches GNSS) tracks Schaltsekunden und überträgt UTC-Zeit direkt von der Konstellation.
Ich bin nicht mit NMEA, aber das SiRF-binary-Protokoll. Es scheint, dass die 16 Sekunden sind auch entfiel hier die timestamp-ich komme aus dem Modul ist nur 1-2 Sekunden mit meinem NTP synchronisiert die Zeit auf meinem PC.
InformationsquelleAutor Geoffrey | 2014-02-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ersten Division durch 86400; der Rest kann verwendet werden, trivial, um die HH:MM:SS Teil von Ihrem Ergebnis. Nun, Sie sind Links mit einer Anzahl von Tagen seit dem Jan 1 1970. Ich würde dann einstellen, dass durch eine Konstante zu sein, die Anzahl der Tage, die (möglicherweise negativen) seit Mar 1 2000; dies ist, weil 2000 ist ein Vielfaches von 400, Schaltjahr-Zyklus, so dass es leicht (oder zumindest leichter), zu zählen, wie viele Schaltjahre sind vergangen, mittels division.
Anstatt zu versuchen, diese näher erläutern, ich Verweise Sie auf meine Umsetzung:
http://git.musl-libc.org/cgit/musl/tree/src/time/__secs_to_tm.c?h=v0.9.15
Ich habe noch nie gedacht, dass ein Teil. Ich denke nur, es macht das handling der leap-Jahre in Einheiten von Tagen leichter, denn der extra Tag genau am Ende des Jahres, eher als in der Mitte.
Die Römer Schalttag in der traditionellen letzten Monat (Februar). Sie rückt auch der 1. Tag des Jahres von irgendwann im März bis zum 1.Januar.
InformationsquelleAutor R..
Es ist nicht klar, warum Sie nicht verwenden die standard-Bibliothek; wenn die Größe ist ein Problem, nur das library-Komponenten von Ihrem code verwendet werden, verknüpft werden, und
time_t
zustruct tm
Konvertierung wird ziemlich klein, aber noch wichtiger ist die richtige und eficient.Jedoch eine bessere Frage ist, warum würden Sie nicht verwenden die Daten direkt aus dem GPS-Modul? Es ist in der achter-Feld der standard -RMC-Satz, dass wird fast sicher vom Gerät ausgegeben.
Beispiel für 25. November 2011:
$GPRMC,001225,A,2832.1834,N,08101.0536,W,12,25,251211,1.2,E,A*03
Fair genug, aber vielleicht das problem, das Sie lösen müssen, ist das fehlen der standard-Bibliothek?
Ich weiß nicht, über SiRF, aber uBlox kann die Ausgabe sowohl UBX und NMEA gemischt. Während SiRF proprietäre NMEA ist allgegenwärtig, so mit NMEA gibt Ihnen größere Portabilität zu.
Dies ist ein one-off-Projekt, Portierung ist nicht gewünscht. Auch während der NMEA ist tragbar, es ist auch ein text-basiertes Protokoll, das Ressourcen verschwendet, SiRF Binär und ist viel einfacher Prozessor-Weise zu handhaben.
Fair genug. Ich glaube, meine Antwort bleibt nützlich, um jemand anderes handling von GPS-Daten - ich werde es verlassen, wenn es Ihnen nichts ausmacht? Ich schlage vor, jedoch, dass die Verwendung einer C-Bibliothek ist immer noch eine option - es gibt eine Reihe von portable Implementierungen. Newlib zum Beispiel - Sie konnte auch nur mit den source-code für
mktime
direkt und verwerfen Sie den rest.InformationsquelleAutor Clifford
Hier ist eine portable Implementierung der
mktime()
. Es enthält Unterstützung für die Sommerzeit, könnten Sie Sie entfernen, um reduzieren Sie die Größe etwas für die UTC nur. Es normalisiert auch die Daten (also wenn zum Beispiel Sie hatte 65 Sekunden, wäre es erhöhen Sie die Minuten und die Sekunden einzustellen, um 5, also vielleicht hat ein gewisser Aufwand, die Sie nicht brauchen.Scheint es etwas komplizierter als die Lösung, die Sie da angekommen sind, möchten Sie vielleicht zu prüfen, ob es einen Grund dafür? Ich würde vielleicht implementieren Sie beide als "test" (auf einem PC und nicht eingebettet) und Durchlaufen eine Vielzahl von Zeit-Zeit-Werte und vergleichen die Ergebnisse mit der PC-compiler, die eigenen
std::mktime
(mit C++ zu vermeiden wird der name clash-die zimmerreserviereung, ohne das umbenennen). Wenn Sie alle produzieren identische Ergebnisse, verwenden Sie dann die Schnellste/kleinste Umsetzung als erforderlich, ansonsten verwenden Sie die eine, die richtige!Ich denke, dass der typische Bibliothek
mktime
führt einen binären Vergleich der Konvergenz der Rückkehr vonlocaltime()
mit dem Ziel. Dies ist weniger effizient als eine direkte kalendarischen Berechnung, aber ich vermute, getan, um sicherzustellen, dass ein round-trip-Konvertierung vonstruct tm
zutime_t
(oder Umgekehrt) und wieder zurück führt zum selben Ergebnis. Die portable Implementierung, die ich oben angedeutet verwendet die gleiche Technik Konvergenz, sondern ersetztlocaltime()
zum entfernen von Bibliothek-Abhängigkeiten. Auf Reflexion daher vermute ich, dass die direkte Berechnung Methode ist vorzuziehen, in Ihrem Fall, da Sie nicht brauchen, Reversibilität - so lange, wie es richtig ist, natürlich.InformationsquelleAutor Clifford