Существует уже функция, называемая toISOString()
:
var date = new Date();
date.toISOString(); //"2011-12-19T15:28:46.493Z"
Если вы каким-то образом находитесь в браузере , который не работает, t поддержите его, я вас покрыл:
if ( !Date.prototype.toISOString ) {
( function() {
function pad(number) {
var r = String(number);
if ( r.length === 1 ) {
r = '0' + r;
}
return r;
}
Date.prototype.toISOString = function() {
return this.getUTCFullYear()
+ '-' + pad( this.getUTCMonth() + 1 )
+ '-' + pad( this.getUTCDate() )
+ 'T' + pad( this.getUTCHours() )
+ ':' + pad( this.getUTCMinutes() )
+ ':' + pad( this.getUTCSeconds() )
+ '.' + String( (this.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 )
+ 'Z';
};
}() );
}
Это может быть надежно воспроизведено (или не воспроизведено, в зависимости от того, что Вы хотите) с openjdk version "1.8.0_222"
(используемый в моем анализе), OpenJDK 12.0.1
(по словам Oleksandr Pyrohov) и OpenJDK 13 (по словам Carlos Heuberger).
я выполнил код с -XX:+PrintCompilation
достаточно раз для получения обоих поведений и здесь являюсь различиями.
Ошибочная реализация (отображает вывод):
--- Previous lines are identical in both
54 17 3 java.lang.AbstractStringBuilder::<init> (12 bytes)
54 23 3 LoopOutPut::test (57 bytes)
54 18 3 java.lang.String::<init> (82 bytes)
55 21 3 java.lang.AbstractStringBuilder::append (62 bytes)
55 26 4 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes)
55 20 3 java.lang.StringBuilder::<init> (7 bytes)
56 19 3 java.lang.StringBuilder::toString (17 bytes)
56 25 3 java.lang.Integer::getChars (131 bytes)
56 22 3 java.lang.StringBuilder::append (8 bytes)
56 27 4 java.lang.String::equals (81 bytes)
56 10 3 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes) made not entrant
56 28 4 java.lang.AbstractStringBuilder::append (50 bytes)
56 29 4 java.lang.String::getChars (62 bytes)
56 24 3 java.lang.Integer::stringSize (21 bytes)
58 14 3 java.lang.String::getChars (62 bytes) made not entrant
58 33 4 LoopOutPut::test (57 bytes)
59 13 3 java.lang.AbstractStringBuilder::append (50 bytes) made not entrant
59 34 4 java.lang.Integer::getChars (131 bytes)
60 3 3 java.lang.String::equals (81 bytes) made not entrant
60 30 4 java.util.Arrays::copyOfRange (63 bytes)
61 25 3 java.lang.Integer::getChars (131 bytes) made not entrant
61 32 4 java.lang.String::<init> (82 bytes)
61 16 3 java.util.Arrays::copyOfRange (63 bytes) made not entrant
61 31 4 java.lang.AbstractStringBuilder::append (62 bytes)
61 23 3 LoopOutPut::test (57 bytes) made not entrant
61 33 4 LoopOutPut::test (57 bytes) made not entrant
62 35 3 LoopOutPut::test (57 bytes)
63 36 4 java.lang.StringBuilder::append (8 bytes)
63 18 3 java.lang.String::<init> (82 bytes) made not entrant
63 38 4 java.lang.StringBuilder::append (8 bytes)
64 21 3 java.lang.AbstractStringBuilder::append (62 bytes) made not entrant
Корректное выполнение (никакой дисплей):
--- Previous lines identical in both
55 23 3 LoopOutPut::test (57 bytes)
55 17 3 java.lang.AbstractStringBuilder::<init> (12 bytes)
56 18 3 java.lang.String::<init> (82 bytes)
56 20 3 java.lang.StringBuilder::<init> (7 bytes)
56 21 3 java.lang.AbstractStringBuilder::append (62 bytes)
56 26 4 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes)
56 19 3 java.lang.StringBuilder::toString (17 bytes)
57 22 3 java.lang.StringBuilder::append (8 bytes)
57 24 3 java.lang.Integer::stringSize (21 bytes)
57 25 3 java.lang.Integer::getChars (131 bytes)
57 27 4 java.lang.String::equals (81 bytes)
57 28 4 java.lang.AbstractStringBuilder::append (50 bytes)
57 10 3 java.lang.AbstractStringBuilder::ensureCapacityInternal (27 bytes) made not entrant
57 29 4 java.util.Arrays::copyOfRange (63 bytes)
60 16 3 java.util.Arrays::copyOfRange (63 bytes) made not entrant
60 13 3 java.lang.AbstractStringBuilder::append (50 bytes) made not entrant
60 33 4 LoopOutPut::test (57 bytes)
60 34 4 java.lang.Integer::getChars (131 bytes)
61 3 3 java.lang.String::equals (81 bytes) made not entrant
61 32 4 java.lang.String::<init> (82 bytes)
62 25 3 java.lang.Integer::getChars (131 bytes) made not entrant
62 30 4 java.lang.AbstractStringBuilder::append (62 bytes)
63 18 3 java.lang.String::<init> (82 bytes) made not entrant
63 31 4 java.lang.String::getChars (62 bytes)
Мы можем заметить одну значительную разницу. С корректным выполнением мы компилируем test()
дважды. Однажды в начале, и еще раз впоследствии (по-видимому, потому что JIT замечает, насколько горячий метод). В ошибочном выполнении test()
компилируется (или декомпилируется) 5 времена.
Кроме того, выполнение с -XX:-TieredCompilation
(который или интерпретирует или использует C2
) или с [1 110] (который вынуждает компиляцию работать в основном потоке, вместо параллельно), вывод , гарантировал , и с 30 000 повторений распечатывает много материала, таким образом, C2
компилятор, кажется, преступник. Это подтверждено путем выполнения с [1 112], который отключает C2
и не производит вывод (останавливающийся на шоу уровня 4 ошибка снова).
В корректном выполнении, метод сначала компилируется с [1 117] компиляция Уровня 3 , затем впоследствии с Уровнем 4.
В ошибочном выполнении, предыдущие компиляции являются discared (made non entrant
), и это снова компилируется на Уровне 3 (который является C1
, см. предыдущую ссылку).
, Таким образом, это определенно - ошибка в [1 116], хотя я не абсолютно уверен, влияет ли то, что это возвращается к компиляции Уровня 3, на него (и почему это возвращается к уровню 3, столько неуверенности все еще).
можно генерировать ассемблерный код со следующей строкой для движения еще глубже в кроличью нору (также см. это для включения печати блока).
java -XX:+PrintCompilation -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly LoopOutPut > broken.asm
В этой точке я начинаю заканчиваться навыки, ошибочное поведение начинает показывать, когда предыдущие скомпилированные версии отбрасываются, но что небольшие навыки блока, которые я имею, с 90-х, таким образом, я позволю кому-то более умному, чем я, берут его отсюда.
вероятно, что уже существует отчет об ошибках об этом, так как код был представлен OP кем-то еще, и как весь код , C2 не без ошибок . Я надеюсь, что этот анализ был так же информативен другим, как это было мне.
Как почтенный apangin, на который указывают в комментариях, это недавняя ошибка . Очень обязанный всем заинтересованным и услужливым людям :)
Не знайте, почему Java дает такой случайный вывод, но проблема находится в Вашей конкатенации, которая перестала работать для больших значений i
внутренняя часть for
цикл.
, Если Вы заменяете String value = i + "";
строка String value = String.valueOf(i) ;
Ваши работы кода как ожидалось.
Конкатенация с помощью +
для преобразования интервала для строкового представления является собственной и могла бы быть багги (Странно, мы основываем его теперь, вероятно) и вызываем такую проблему.
Примечание: Я уменьшил значение меня внутри для цикла к 10 000, и я не столкнулся с проблемой с +
конкатенация.
об Этой проблеме нужно сообщить заинтересованным сторонам Java & они могут дать свое мнение о том же.
Редактирование я обновил значение меня в для цикла к 3 миллионам и видел новый набор ошибок как указано ниже:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at java.lang.Integer.getChars(Integer.java:463)
at java.lang.Integer.toString(Integer.java:402)
at java.lang.String.valueOf(String.java:3099)
at solving.LoopOutPut.test(LoopOutPut.java:16)
at solving.LoopOutPut.main(LoopOutPut.java:8)
Моя версия Java равняется 8.
Это честно довольно нечетно, поскольку тот код никогда не должен технически производить потому что...
int i = 8;
while ((i -= 3) > 0);
... должен всегда приводить к i
являющийся -1
(8 - 3 = 5; 5 - 3 = 2; 2 - 3 =-1). То, что является еще более странным, то, что это никогда выводы в режиме отладки моего IDE.
Интересно, момент я добавляю проверку перед преобразованием в String
, затем без проблем...
public void test() {
int i = 8;
while ((i -= 3) > 0);
if(i != -1) { System.out.println("Not -1"); }
String value = String.valueOf(i);
if (!"-1".equalsIgnoreCase(value)) {
System.out.println(value);
System.out.println(i);
}
}
Всего две точки хорошей практики кодирования...
String.valueOf()
.equals()
, а не аргумент, таким образом минимизировав NullPointerExceptions. единственный способ, которым я заставил это не происходить, был при помощи String.format()
public void test() {
int i = 8;
while ((i -= 3) > 0);
String value = String.format("%d", i);
if (!"-1".equalsIgnoreCase(value)) {
System.out.println(value);
System.out.println(i);
}
}
... по существу просто похоже, что Java требуется определенное время, чтобы отдышаться :)
РЕДАКТИРОВАНИЕ: Это может быть абсолютно случайно, но там, кажется, некоторая корреспонденция между значением, которое распечатывает и ТАБЛИЦА ASCII .
i
= -1
, отображенный символ /
(десятичное значение ASCII 47) i
= -2
, отображенный символ .
(десятичное значение ASCII 46) i
= -3
, отображенный символ -
(десятичное значение ASCII 45) i
= -4
, отображенный символ ,
(десятичное значение ASCII 44) i
= -5
, отображенный символ +
(десятичное значение ASCII 43) i
= -6
, отображенный символ *
(десятичное значение ASCII 42) i
= -7
, отображенный символ )
(десятичное значение ASCII 41) i
= -8
, отображенный символ (
(десятичное значение ASCII 40) i
= -9
, отображенный символ '
(десятичное значение ASCII 39) , Что действительно интересно, то, что символ в десятичном числе ASCII 48 является значением 0
и 48 - 1 = 47 (символ /
), и т.д.