Uhrzeitberechnung
Michael Schröpl
- perl
Hallo Leute,
ich bin gerade dabei, ein bißchen in Perl mit Uhrzeiten herumzurechnen.
Was ich haben möchte, das ist eine saubere Erkennung eines Datumswechsels auf meiner Maschine (weil sich mit diesem Datumswechsel die Aufgabenstellung meines laufenden Programms ändert).
Das sieht ja auf den ersten Blick nicht so arg schwer aus:
my $now = time();
my $end_of_day = $now - ($now % 86400) + 86400;
und dann
while (time() <= $end_of_day)
{ ... }
Tja, wenn ich nun in Greenwich wohnen würde und es keine Sommerzeit gäbe, dann wäre ich bereits fertig.
Beides ist aber nicht der Fall (vor allem im Moment).
Mein Wert liegt genau zwei Stunden daneben (die 'Umschaltung' erfolgt derzeit also um 2 Uhr früh).
Eine der beiden Stunden kann ich "per Definition" abziehen, weil ich die Zeitzone, in welcher das Programm laufen wird, mit ziemlicher Sicherheit kenne (nämlich "hier").
Ich fände es aber schöner, wenn ich irgendwo die Anzahl der Zeitzonen ablesen könnte. Mein erster Blick fiel auf die Environment-Variable "TZ" - aber da steht "MEZ" drin, nicht etwa "+1" oder etwas ähnlich Numerisches, was sich als Faktor für 3600 eignen würde, so daß ich das Produkt der beiden von meinem time()-Wert abziehen könnte. Eine Tabelle aller symbolischen TZ-Werte in mein Programm einzubauen fände ich nicht sonderlich ästhetisch - zumal die womöglich noch nicht mal universell eindeutig sein müssen, denke ich mal ...
Die andere Stunde Differenz ist dann die Sommerzeit.
Über localtime() bekomme ich im letzten der vielen Parameter "isdst" ein Flag, das mir (laut Google - meine Perl5-Doku setzt an dieser Stelle einfach Kenntnisse des C-Compilers voraus, pfui Teufel) sagt, ob wir Sommerzeit haben oder nicht oder ob das System darüber keine Aussage machen kann ... (letzteres fände ich nicht so toll).
Auf meiner Maschine bekomme ich in der Tat den erfreulichen Wert 1 zurück. Und im Moment ist es ja wohl offensichtlich so, daß "Sommerzeit" identisch ist mit "genau eine Stunde Verschiebung" ... solches implizite Wissen möchte ich allerdings nicht so wahnsinnig gerne in meinen Quelltext einbrennen, falls es auch irgendwie eine andere Lösung gäbe, wo man die tatsächliche Zeit-Differenz ablesen könnte.
Was ich auch tun könnte, das wäre, mit localtime() und gmtime() die beiden entsprechenden Uhrzeiten als Komponenten-Felder zu berechnen und dann irgendwie daraus die Differenz zu berechnen.
Das würde zwar sämtliche Effekte subsummieren ... aber ich müßte beides erst mal wieder in Sekunden zurückrechnen und dann die Differenz aus beiden Werten bilden ... und wie mache ich das im allgemeinen Fall, ohne komplette Kalender- und Schaltjahresrechnerei?
Ich könnte mit der Differenz der beiden Stunden-Werte arbeiten und den Rest vernachlässigen ... dann aber würde ich wieder implizite Annahmen über meinen Standort verwenden müssen ... oder?
Daher meine Frage:
Lösungen _ohne_ erforderliche Installation irgendwelcher CPAN-Module
würde ich bevorzugen (das Zeug müßte ggf. auf einen Haufen Produktionsmaschinen drauf - das würde ich gerne vermeiden, zumal ich das normalen CPAN-online-Installationsverfahren wg. Firewall nicht so ohne weiteres verwenden darf).
Viele Grüße
Michael
Hi,
- Gibt es in Perl irgendwelche (von mir übersehenen) Variablen,
Funktionen oder was auch immer, welche mir (zuverlässiger als oben
beschrieben und ohne viel Rechnerei)
was hälst Du davon, mittels Date::Calc (falls nötig) einen Tag hinzuzuzählen, und Time::Local zu verwenden, um "heute plus 1, 0:00 Uhr" zu ermitteln?
Lösungen _ohne_ erforderliche Installation irgendwelcher CPAN-Module
Hm, auch ohne Standard-Module? :-)
(das Zeug müßte ggf. auf einen Haufen Produktionsmaschinen drauf - das würde ich gerne vermeiden, zumal ich das normalen CPAN-online-Installationsverfahren wg. Firewall nicht so ohne weiteres verwenden darf).
Bei hinreichend gleichartigen Systemen reicht vermutlich scp oder ähnliches.
Cheatah
Hallo Cheatah,
Lösungen _ohne_ erforderliche Installation irgendwelcher CPAN-Module
Hm, auch ohne Standard-Module? :-)
ich habe auf der Entwicklungsmaschine Perl 5.005_03 drauf, das installiere ich aber nicht selbst.
Was genau auf den anderen Maschinen drauf ist (womöglich weniger), weiß ich im Moment noch nicht so genau - und auch nicht, wie viele Maschinen das letztlich werden ... es ist nicht mal ausgeschlossen, daß mein Daemon in ein paar Monaten eine eigene Maschine bekommt und mit den anderen Maschinen kommunizieren wird, das ist alles noch ein wenig arg im Fluß ...
(das Zeug müßte ggf. auf einen Haufen Produktionsmaschinen drauf -
das würde ich gerne vermeiden, zumal ich das normalen CPAN-online-
Installationsverfahren wg. Firewall nicht so ohne weiteres verwenden
darf).
Bei hinreichend gleichartigen Systemen reicht vermutlich scp oder
ähnliches.
Ups - das sagt mir jetzt erst mal nichts.
Was die Maschinen angeht: Ja, die sollten ziemlich gleichartig sein.
Viele Grüße
Michael
Hi,
ich habe auf der Entwicklungsmaschine Perl 5.005_03 drauf,
hm, eigentlich sollte das reichen. Allerdings solltest Du Dich auch nicht scheuen, Deinem Arbeitgeber gewisse Minimalanforderungen vorzuschreiben - beispielsweise Perl ;-) aber eben auch die wenigen Module. AFAIK ist Time::Date reiner Perl-Code, braucht also nicht mal kompiliert zu werden; das kann _jeder_ in Minutenschnelle installieren.
Was genau auf den anderen Maschinen drauf ist (womöglich weniger), weiß ich im Moment noch nicht so genau - und auch nicht, wie viele Maschinen das letztlich werden ... es ist nicht mal ausgeschlossen, daß mein Daemon in ein paar Monaten eine eigene Maschine bekommt und mit den anderen Maschinen kommunizieren wird, das ist alles noch ein wenig arg im Fluß ...
Argh, ich _liebe_ so exakte Anforderungen :-)
Bei hinreichend gleichartigen Systemen reicht vermutlich scp oder
ähnliches.
Ups - das sagt mir jetzt erst mal nichts.
scp ist "secure copy", mit dem Du unter Unix zwischen verschiedenen Maschinen kopieren kannst. Wenn Dir FTP, CVS o.ä. lieber ist, kannst Du das natürlich auch nehmen :-)
Was die Maschinen angeht: Ja, die sollten ziemlich gleichartig sein.
Das "gleichartig" bezog sich vor allem darauf, dass manche Module kompiliert sein müssen. Somit hättest Du also große Vorteile, wenn Du später ein "komplexeres" Modul brauchst.
Cheatah
Hallo Cheatah,
Allerdings solltest Du Dich auch nicht scheuen, Deinem
Arbeitgeber gewisse Minimalanforderungen vorzuschreiben -
beispielsweise Perl ;-) aber eben auch die wenigen Module.
das Problem ist, daß auf der Maschine bereits ein Produkt läuft, das eine definierte Installations- und Betriebsvoraussetzung hat, und ich zu diesem Produkt nur add-ons baue. Das Produkt ist von einer Partnerfirma - denen kann ich nicht vorschreiben, was ich alles gerne auf der Maschine hätte.
Wenn ich aber irgendwelches Zeug am Perl-Interpreter ändere (den die auch voraussetzen - deshalb ist er ja bereits verfügbar) und dann läuft irgendwas von _deren_ Software nicht mehr, dann bin natürlich _ich_ schuld ... (bis zum Beweis des Gegenteils).
Deshalb möchte ich an dieser Stelle lieber gar nicht anfangen, etwas drehen zu müssen. Je autarker meine add-ons sind, desto weniger besteht die Gefahr, daß ich versehentlich irgendwas kaputt mache.
Was genau auf den anderen Maschinen drauf ist (womöglich
weniger), weiß ich im Moment noch nicht so genau - und
auch nicht, wie viele Maschinen das letztlich werden ...
es ist nicht mal ausgeschlossen, daß mein Daemon in ein
paar Monaten eine eigene Maschine bekommt und mit den
anderen Maschinen kommunizieren wird, das ist alles noch
ein wenig arg im Fluß ...
Argh, ich _liebe_ so exakte Anforderungen :-)
Die Anforderung lautet im Wesentlichen: "Die bisherige Lösung ist untauglich, und der Source-Code ist nicht verfügbar - also wegwerfen und neu schreiben." Und das mache ich gerade. ;-)
Daß es letztlich viele gleiche Maschinen werden und daß die Idee besteht, bestimmte Services von dedizierten anderen Maschinen zu importieren, ist eine vergleichsweise neue Architektur-Randbedingung (mit der ich aber prima leben kann, in einem Universum von HTTP und maschinenübergreifenden mySQL-Zugriffen).
Viele Grüße
Michael
Hi,
das Problem ist, daß auf der Maschine bereits ein Produkt läuft, das eine definierte Installations- und Betriebsvoraussetzung hat, und ich zu diesem Produkt nur add-ons baue. Das Produkt ist von einer Partnerfirma - denen kann ich nicht vorschreiben, was ich alles gerne auf der Maschine hätte.
nun, im Zweifel kannst Du den Code von Time/Local.pm lesen und verwenden...
Wenn ich aber irgendwelches Zeug am Perl-Interpreter ändere (den die auch voraussetzen - deshalb ist er ja bereits verfügbar) und dann läuft irgendwas von _deren_ Software nicht mehr, dann bin natürlich _ich_ schuld ... (bis zum Beweis des Gegenteils).
Ein _neues_ Modul kann nur mit erheblicher Mühe Probleme verursachen... ;-)
Je autarker meine add-ons sind, desto weniger besteht die Gefahr, daß ich versehentlich irgendwas kaputt mache.
Ja.
Die Anforderung lautet im Wesentlichen: "Die bisherige Lösung ist untauglich, und der Source-Code ist nicht verfügbar - also wegwerfen und neu schreiben."
Eieiei, sowas kenne ich :-)
Cheatah
Hallo Michael,
Du könntest IMHO das sehr wohl mit den Ergebnissen von gmtime() und localtime() hinbekommen. [1]
Eigentlich brauchst Du ja nur am Beginn des Scripts die Differentz der Stunden ermitteln und dementsprechend $end_of_day korrigieren.
Wenn localtime nicht mehr die richtige Zeit liefert, dann wird auf diesem System sowieso Hopfen und Malz verloren sein;-)
Aber ich hab' da mal eine Gegenfrage:
Warum verwendest Du nicht gleich die Ergebnisse von localtime() für den Datumssprung?
Der einzige Grund könnte IMHO nur der sein, daß das ständige Berechnen der Werte mit localtime zu rechenintesiv wäre.
Grüße
Klaus
[1] Allerdings ist das nicht wirklich protabel, da beispielsweise unter VMS gmtime nicht, oder auch nur nicht immer, verfügbar ist. Ich hatte einige Zeit mit VMS 6.x und Perl 5.005 zu tun, da war es nicht implemetiert, da das OS es nicht konnte. Da mußte ich dann irgendwie auf ein LOCIGAL ausweichen, oder so, weiß nicht mehr so genau.
Hallo Klaus,
Aber ich hab' da mal eine Gegenfrage:
Warum verwendest Du nicht gleich die Ergebnisse von localtime() für den
Datumssprung?
Der einzige Grund könnte IMHO nur der sein, daß das ständige Berechnen
der Werte mit localtime zu rechenintesiv wäre.
das habe ich im Detail noch nicht ausprobiert. Müßte ich aber in der Tat mal tun - von der Software-Abhängigkeit wäre das am günstigsten.
Im Wesentlichen läuft mein Programm als eine Art daemon, der ständig nachschaut, ob er etwas zu tun hat, und wenn nicht, dann eine Sekunde "sleep()"ed - und danach prüfen möchte, ob noch "heute" ist (denn falls nicht, ist seine Eingabequelle gerade vertrocknet und er muß sich nach einer neuen umsehen).
Insofern wäre also ziemlich genau ein Aufruf pro Sekunde fällig, und da wäre mir time() halt schon ressourcenschonender vorgekommen als localtime(), zumal auf der Maschine noch ein Haufen anderer Sachen läuft (etwa die mySQL-Datenbank, in welche mein daemon die angenommenen Daten pumpt, und der Apache, über den sie ggf. ausgeliefert werden, und ein paar andere nette Dinge). Mein Zeug macht ansonsten schon genug Maschinenlast ...
[1] Allerdings ist das nicht wirklich protabel, da beispielsweise
unter VMS gmtime nicht, oder auch nur nicht immer, verfügbar ist.
Ich hatte einige Zeit mit VMS 6.x und Perl 5.005 zu tun, da war es
nicht implemetiert, da das OS es nicht konnte. Da mußte ich dann
irgendwie auf ein LOCIGAL ausweichen, oder so, weiß nicht mehr so
genau.
Das muß es nicht sein - wenn es unter Solaris läuft, bin ich zufrieden.
Viele Grüße
Michael
Hallo Klaus,
Du könntest IMHO das sehr wohl mit den Ergebnissen von
gmtime() und localtime() hinbekommen. [1]
Eigentlich brauchst Du ja nur am Beginn des Scripts die
Differenz der Stunden ermitteln und dementsprechend
$end_of_day korrigieren.
Ich muß nicht $end_of_day korrigieren, sondern $now.
Was ich bräuchte, das wäre eine time()-Funktion im
localtime-Universum statt im GMT-Universum ...
Warum verwendest Du nicht gleich die Ergebnisse von
localtime() für den Datumssprung?
Das ist mir durch Deine Gegenfrage erst wieder klar geworden:
Weil ich den Wert von $end_of_day auch noch für andere Dinge brauche. Der ist ein Eingabeparameter in die Funktion, die zu Beginn des neuen Tages als erstes zu laufen hat.
Viele Grüße
Michael
Moin, Michael!
ich bin gerade dabei, ein bißchen in Perl mit Uhrzeiten herumzurechnen.
Was ich haben möchte, das ist eine saubere Erkennung eines Datumswechsels auf meiner Maschine (weil sich mit diesem Datumswechsel die Aufgabenstellung meines laufenden Programms ändert).
Wenn das einzige, was du willst, die exakte Zeit der lokalen Maschine ist (und dir herzlich egal ist, wie diese Zeit gestellt wird), dann vertraue doch einfach dem externen Kommando "date", welches dir in beliebiger Formatierung sagt, wie spät es die Maschine gerade hat - und wenn's Null Uhr ist, machst du programm-mäßig eben was anderes als vorher.
Ansonsten habe ich den Verdacht, daß die durch time() übermittelte Unix-Zeit exakt die gleiche Zeitbasis hat wie die lokale Uhr, die mit date abgefragt wird. Und das wäre doch genau das, was du brauchst, oder?
- Sven Rautenberg
Hi,
dann vertraue doch einfach dem externen Kommando "date",
etwas proprietär, aber bei definierter Umgebung nicht schlecht. Unter Unix hilft übrigens:
date --date=tomorrow +%Y-%m-%d
Cheatah
Hi Sven,
Wenn das einzige, was du willst, die exakte Zeit der lokalen Maschine
ist (und dir herzlich egal ist, wie diese Zeit gestellt wird), dann
vertraue doch einfach dem externen Kommando "date", welches dir in
beliebiger Formatierung sagt, wie spät es die Maschine gerade hat -
und wenn's Null Uhr ist, machst du programm-mäßig eben was anderes als
vorher.
Ich weiß nicht, wie exakt um 0 Uhr ich Gelegenheit bekomme, auf die Uhr zu sehen. Es kann sein, daß ich zu diesem Zeitpunkt gerade zu tun habe - und solange ich zu tun habe, will ich bestimmt nicht umschalten.
Wahrscheinlich will ich ohnehin nicht genau um Mitternacht umschalten, weil ich im Moment nicht so ganz sicher bin, wann _genau_ meine Nachrichtenquelle vertrocknet und die nächste zu senden beginnt.
Den Sendebeginn darf ich durchaus erst mal verpassen - das puffert jemand anders für mich, ich muß nur dessen Ausgabe irgendwann zu lesen anfangen. Aber vor dem Beginn der Verarbeitung der nächsten Eingabequelle habe ich ein tägliches Housekeeping zu erledigen, das eine ganze Weile dauern kann ... deshalb möchte ich damit so früh wie möglich anfangen, weil sich um diese Zeit noch ein paar andere Last-Fresser um die CPU schlagen ... und das Aufholen der Verarbeitung der nächsten Eingabe kann auch teuer werden, wenn ich mir zu viel Zeit lasse ... um zwei Stunden wie bisher darf ich mich jedenfalls nicht irren. ;-)
Im Vergleich zu "date" (externe Abhängigkeit und zusätzlicher Prozeßstart) gefällt mir allerdings "localtime()" im Moment deutlich besser.
Viele Grüße
Michael
Yo (und total off-topic)!
Ich weiß nicht, wie exakt um 0 Uhr ich Gelegenheit bekomme, auf die Uhr zu sehen. Es kann sein, daß ich zu diesem Zeitpunkt gerade zu tun habe - und solange ich zu tun habe, will ich bestimmt nicht umschalten.
Wahrscheinlich will ich ohnehin nicht genau um Mitternacht umschalten, weil ich im Moment nicht so ganz sicher bin, wann _genau_ meine Nachrichtenquelle vertrocknet und die nächste zu senden beginnt.
Den Sendebeginn darf ich durchaus erst mal verpassen - das puffert jemand anders für mich, ich muß nur dessen Ausgabe irgendwann zu lesen anfangen.
Das klingt für mich alles sehr nach geheimdienstlicher Tätigkeit und könnte so auch prima in Spionageromanen geschrieben stehen. Nur so als *g* zum Feiertag. ;)
- Sven Rautenberg
Moin,
Über localtime() bekomme ich im letzten der vielen Parameter "isdst" ein Flag, das mir (laut Google - meine Perl5-Doku setzt an dieser Stelle einfach Kenntnisse des C-Compilers voraus, pfui Teufel)
Ein man localtime war dir wohl zu einfach?
--
Henryk Plötz
Grüße aus Berlin
Hi Henryk,
Ein man localtime war dir wohl zu einfach?
um auf die Idee zu kommen, daß solche Funktionen in Perl und C tatsächlich identisch heißen, müßte ich halt mehr als fast gar nichts mehr über C wissen ... mein letztes eigenes C-Programm war in der ersten Hälfte der 90er.
Und meine sporadischen Blicke in den Apache-Quelltext zeigen mir immer wieder, wie wenig C und (mein Subset von) Perl miteinander zu tun haben (string-Funktionen, Typ-Konvertierungen etc) ...
In der Tat steht dort aber beispielsweise:
Nur: Wie komme ich von Perl aus an solche Informationen heran?
Über localtime() ja offenbar nicht ...
Viele Grüße
Michael