• Es freut uns dass du in unser Minecraft Forum gefunden hast. Hier kannst du mit über 130.000 Minecraft Fans über Minecraft diskutieren, Fragen stellen und anderen helfen. In diesem Minecraft Forum kannst du auch nach Teammitgliedern, Administratoren, Moderatoren , Supporter oder Sponsoren suchen. Gerne kannst du im Offtopic Bereich unseres Minecraft Forums auch über nicht Minecraft spezifische Themen reden. Wir hoffen dir gefällt es in unserem Minecraft Forum!

Bungeecord long, system#currenttimemillis

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
Hallo,
ich programmiere derzeit ein BanSystem und habe dabei ein Problem.
Ich kann einen Spieler ganz normal bannen und es klappt, aber ab einem bestimmten Wert (ca. 2 Monate) klappt es nicht mehr, da long nach einem bestimmten Wert nicht mehr größer, sondern kleiner wird, da die Zahl zu groß wird. Ich habe dieses Problem zwar gelöst, indem ich die Zahlen nicht mehr als Millisekunden sondern als Sekunden abspeichere, etc.. Aber ich bin jetzt auf dieses Problem noch einmal gestoßen, da ich einen /check befehl machen möchte und dort den Entbannungsdatum, als Nachricht senden möchte und dafür muss ich einen SimpleDateFormat erstellen und beim erstellen eine Date muss ich die Zahl in Millisekunden angeben. Hat jemand dafür eine Lösung, bzw. weiß jemand wie ich das fixen kann?​
 

Scrayos

Vorarbeiter
Registriert
11 Februar 2012
Beiträge
296
Alter
29
Diamanten
338
Minecraft
Scrayos
Hallo und frohes Fest!

Ich bezweifle sehr, dass du bei deinem Bann-System an die Grenzen eines Longs stößt. Erst recht, wenn du sogar "nur" Millisekunden-Präzision verwendest. Ein Long kann ja Werte von -(2^63) bis (2^63)-1 halten. Die maximal mögliche Zahl im positiven Bereich wäre somit 9.223.372.036.854.775.807, was (wenn man es als Unix-Epoch, also als (Milli-)Sekunden seit dem 01. Januar 1970 interpretiert) dem 17. August 292278994 entsprechen würde. Du siehst also, Longs können riesige Zahlen halten. So groß, dass wir sie uns in diesem zeitlichen Kontext kaum vorstellen können.

Während wir hier also dem Ursprung für dein Problem nachgehen könnten, würde ich dir stattdessen eher die hervorragende, neue Zeit-API von Java (seit Java 8) empfehlen. Du kannst natürlich rohe Zahlen als Zeitpunkte, Zeiträume, Intervalle und Zeitverschiebungen interpretieren, aber es empfiehlt sich definitiv hierfür dedizierte Klassen und Objekte zu verwenden. Hier hättest du schon einmal einen kleinen Einblick in diese neue Schnittstelle: https://www.baeldung.com/java-8-date-time-intro

Und hier wären auch noch ein paar Gründe dafür, warum du unbedingt die neue Zeit-API nutzen solltest, und nicht die antiquarische "Calendar-API": https://www.heise.de/developer/artikel/Die-neue-Date-Time-API-in-Java-8-2198399.html

Um dir schon einmal an paar Begriffe (für eventuelle Google-Fragen) mitzugeben: Du wirst hier aller Wahrscheinlichkeit nach mit Instant für den Zeitpunkt des Banns, Duration für die Dauer des Banns und ggf. LocalDateTime für die Ausgabe dieser Zeitpunkte arbeiten müssen. Die LocalDateTime könntest du dann beispielsweise mit einem DateTimeFormatter in einen String formatieren.

Ich bin mir bewusst, dass du hier von mir etwas viel umfangreicheres bekommen hast, als du vermutlich einfach lösen wollen wirst. Dennoch möchte ich dir wirklich mit Nachdruck ans Herz legen, diesen Sprung zu wagen. Die Zeit-API ermöglicht dir wesentlich besser lesbaren, wartbaren und typsicheren Code zu schreiben. Zeit ist schon komplex genug (spätestens wenn Zeitumstellungen und Zeitzonen dazu kommen), mach' es dir nicht unnötig schwer, indem du mit rohen Zahlen arbeitest.
 

UnityGaming

Workaholic
Registriert
25 Oktober 2015
Beiträge
527
Alter
26
Diamanten
312
Minecraft
FastFelix771
Die Antwort von @Scrayos ist perfekt. Dem ist eigentlich nichts hinzuzufügen.
Ich möchte bloß aus Neugier auf das beschriebene Problem nochmal eingehen.

Meine erste Vermutung wäre, dass irgendwo in deinem Code versehentlich der long zu int konvertiert wird.
ab einem bestimmten Wert (ca. 2 Monate) klappt es nicht mehr, da long nach einem bestimmten Wert nicht mehr größer, sondern kleiner wird, da die Zahl zu groß wird.
Der Java Integer hat einen wesentlich kleineren Zahlenraum, weswegen du vermutlich auf dieses Phänomen stößt.
Integers sind 32 Bit groß und dadurch, dass Java standardmäßig alle Zahlen mit Vorzeichen versieht, halbiert sich der positive Zahlenraum: -2147483648 bis 2147483647 kannst du mit einem int abbilden.
Um die verantwortliche Stelle zu finden, müsstest du allerdings deinen Code mit uns teilen.

Weshalb deine Lösung mit Sekunden funktioniert:
1 Sekunde entspricht 1.000 Millisekunden.
Durch die Nutzung einer anderen Maßeinheit streckst du den Zeitrahmen den dein Zahlenraum jetzt abbilden kann künstlich.
Nimm bspw. mal dieses Tool her und haue da 2147483647 rein: https://www.unixtimestamp.com/
Du wirst im Jahr 2038 rauskommen.

Probiere doch mal jemanden für 20 Jahre zu bannen (oder bau einen Unit-Test ;)) , dann sollte auch dort dein Code wieder brechen, wenn du wirklich irgendwo mit Integers statt Longs arbeitest.
 

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
Die Antwort von @Scrayos ist perfekt. Dem ist eigentlich nichts hinzuzufügen.
Ich möchte bloß aus Neugier auf das beschriebene Problem nochmal eingehen.

Meine erste Vermutung wäre, dass irgendwo in deinem Code versehentlich der long zu int konvertiert wird.

Der Java Integer hat einen wesentlich kleineren Zahlenraum, weswegen du vermutlich auf dieses Phänomen stößt.
Integers sind 32 Bit groß und dadurch, dass Java standardmäßig alle Zahlen mit Vorzeichen versieht, halbiert sich der positive Zahlenraum: -2147483648 bis 2147483647 kannst du mit einem int abbilden.
Um die verantwortliche Stelle zu finden, müsstest du allerdings deinen Code mit uns teilen.

Weshalb deine Lösung mit Sekunden funktioniert:
1 Sekunde entspricht 1.000 Millisekunden.
Durch die Nutzung einer anderen Maßeinheit streckst du den Zeitrahmen den dein Zahlenraum jetzt abbilden kann künstlich.
Nimm bspw. mal dieses Tool her und haue da 2147483647 rein: https://www.unixtimestamp.com/
Du wirst im Jahr 2038 rauskommen.

Probiere doch mal jemanden für 20 Jahre zu bannen (oder bau einen Unit-Test ;)) , dann sollte auch dort dein Code wieder brechen, wenn du wirklich irgendwo mit Integers statt Longs arbeitest.

Ich habe den Verdacht auch gehabt, aber daran liegt es nicht. Ich habe dazu einen Test gemacht, wo ich die gleiche Rechnung in einem neuen Projekt ausprobiert habe

Hier mein TestProjekt:

Code:
    public static void main(String[] args) {
        long test = 1000 * 60 * 60 * 24 * 10;
        System.out.println(test / 1000 / 60 / 60 / 24 + "");
    }

Ausgabe: 10 (ist ja auch richtig so es so, denn 100*60*60*24 ist ja auch 1 Tag)

ABER:

Code:
    public static void main(String[] args) {
        long test = 1000 * 60 * 60 * 24 * 30 * 2;
        System.out.println(test / 1000 / 60 / 60 / 24 / 30 + "");
    }

Ausgabe: 0 (falsch, denn es sollten 2 sein da es 2 Monate sind, denn 1000*60*60*24*30 sind ja 1 Monat)

Ich habe noch mehr Tests gemacht und habe gemerkt, dass die Zahlen nach einem bestimmten Wert kleiner werden.
 

UnityGaming

Workaholic
Registriert
25 Oktober 2015
Beiträge
527
Alter
26
Diamanten
312
Minecraft
FastFelix771
Ausgabe: 10 (ist ja auch richtig so es so, denn 100*60*60*24 ist ja auch 1 Tag)
Kommt bei mir das gleiche heraus.

Ausgabe: 0 (falsch, denn es sollten 2 sein da es 2 Monate sind, denn 1000*60*60*24*30 sind ja 1 Monat)
Wenn ich das mal nachrechne im Taschenrechner ergibt dein Beispiel 0.333333333, da Int und Long Ganzzahlen sind, wird die Kommastelle abgeschnitten, wir landen also bei 0.
Korrektur:
1000 * 60 * 60 * 24 * 30 * 2 = 5184000000 / 1000 / 60 / 60 / 24 / 30 = 2
Falsche Zeile eingerechnet^^

Ich habe noch mehr Tests gemacht und habe gemerkt, dass die Zahlen nach einem bestimmten Wert kleiner werden.
Hast du da ein Beispiel?

Was willst du eigentlich mit dem '+ ""' am Ende bezwecken? Das wirkt sich null auf deine Ausgabe aus und ist total sinnbefreit.
 
Zuletzt bearbeitet:

UnityGaming

Workaholic
Registriert
25 Oktober 2015
Beiträge
527
Alter
26
Diamanten
312
Minecraft
FastFelix771
Nach kurzem selbst ausprobieren hat mir IntelliJ die Lösung bzw. den Fehler gleich an den Schädel geschmettert:
1608924258983.png


Wo wir dann wieder bei dem Problem wären, dass ich dir beschrieben habe.
Folgende Änderung und schon geht das perfekt auf:
Javascript:
    public static void main(String[] args) {
        long test = 1000L * 60 * 60 * 24 * 30 * 2;

        System.out.println(test);
        System.out.println(test / 1000 / 60 / 60 / 24 / 30);
    }

Du musst die Arithmetik dazu zwingen beide Operanden als Long zu betrachten, da er in diesem Fall sonst zu Ints tendiert und lediglich dein Ergebnis in einem Long abgebildet wird.

1000, 60, 24, 30, 2 - das sind per-se erstmal alles Integer-Operanden, drum musst du diese bzw, einen explizit als Long kennzeichnen, mit einem L oder l hinten dran. Dann greift auch die Long-Arithmetik und dir steht für die Berechnung der gesamte Zahlenraum des Long anstatt des Integer zur Verfügung. Java richtet sich nämlich nach dem "größten" Operanden, also wenn du 3 Ints und einen Long zusammenwirfst, wird der Zahlenraum des Long als Grundlage für die Berechnung verwendet.

Lässt sich mMn. mies erklären und ich bin auch kein Mathe-Nerd, aber ich hoffe du verstehst halbwegs was da passiert ist.
Hier wird die quasi gleiche Problematik beschrieben wenn du mit Fließkommazahlen rechnest: https://alvinalexander.com/java/java-int-double-float-mixed-type-division-arithmetic-rules/
 
Zuletzt bearbeitet:

Blura_

Kuhfänger
Registriert
25 Juli 2019
Beiträge
79
Diamanten
300
Minecraft
Blura_
Nach kurzem selbst ausprobieren hat mir IntelliJ die Lösung bzw. den Fehler gleich an den Schädel geschmettert: Anhang anzeigen 18372

Wo wir dann wieder bei dem Problem wären, dass ich dir beschrieben habe.
Folgende Änderung und schon geht das perfekt auf:
Javascript:
    public static void main(String[] args) {
        long test = 1000L * 60 * 60 * 24 * 30 * 2;

        System.out.println(test);
        System.out.println(test / 1000 / 60 / 60 / 24 / 30);
    }

Du musst die Arithmetik dazu zwingen beide Operanden als Long zu betrachten, da er in diesem Fall sonst zu Ints tendiert und lediglich dein Ergebnis in einem Long abgebildet wird.

1000, 60, 24, 30, 2 - das sind per-se erstmal alles Integer-Operanden, drum musst du diese bzw, einen explizit als Long kennzeichnen, mit einem L oder l hinten dran. Dann greift auch die Long-Arithmetik und dir steht für die Berechnung der gesamte Zahlenraum des Long anstatt des Integer zur Verfügung. Java richtet sich nämlich nach dem "größten" Operanden, also wenn du 3 Ints und einen Long zusammenwirfst, wird der Zahlenraum des Long als Grundlage für die Berechnung verwendet.

Lässt sich mMn. mies erklären und ich bin auch kein Mathe-Nerd, aber ich hoffe du verstehst halbwegs was da passiert ist.
Hier wird die quasi gleiche Problematik beschrieben wenn du mit Fließkommazahlen rechnest: https://alvinalexander.com/java/java-int-double-float-mixed-type-division-arithmetic-rules/

ich denke ich habe es verstanden und es hat jetzt auch geklappt...
Danke dir für die Antwort und für deine Mühe :)
Übrigens dieses + "" ist eine angewöhnung von mir, da wenn ich z. B. eine Zahl als String angeben muss, sie zuerst in String umwandeln muss und das mache ich wie folgt: int + "" (ich kann hier die Methode toString nicht verwenden und deshalb '+ "" '​
 

UnityGaming

Workaholic
Registriert
25 Oktober 2015
Beiträge
527
Alter
26
Diamanten
312
Minecraft
FastFelix771
Übrigens dieses + "" ist eine angewöhnung von mir, da wenn ich z. B. eine Zahl als String angeben muss, sie zuerst in String umwandeln muss und das mache ich wie folgt: int + "" (ich kann hier die Methode toString nicht verwenden und deshalb '+ "" '
Furchtbare Angewohnheit. :D

Die print*-Methoden vom PrintStream (System.out ist eine Instanz der PrintStream Klasse) erwarten Parameter vom Typ Object und konvertieren sie selbstständig zu Strings. Da alles von Object erbt, kannst du hier quasi alles als Parameter übergeben.
Für primitive Typen (int/long/boolean usw.) stellt PrintStream ebenfalls die print*-Methoden zur Verfügung, die Namen bleiben gleich dank Method Overloading.

Das tut also überhaupt nicht Not.
 
Oben