!!expr
возвращает логическое значение (true
или false
) в зависимости от правды выражения. Это имеет смысл при использовании в небулевых типах. Рассмотрим эти примеры, особенно третий пример и далее:
!!false === false
!!true === true
!!0 === false
!!parseInt("foo") === false // NaN is falsy
!!1 === true
!!-1 === true // -1 is truthy
!!"" === false // empty string is falsy
!!"foo" === true // non-empty string is truthy
!!"false" === true // ...even if it contains a falsy value
!!window.foo === false // undefined is falsy
!!null === false // null is falsy
!!{} === true // an (empty) object is truthy
!![] === true // an (empty) array is truthy; PHP programmers beware!
Реализация nowInMicrosSinceEpoch()
неверна. Значение в миллисекундах применяется дважды.
Чтобы показать это, вот код Java для печати значений, используемых в nowInMicrosSinceEpoch()
:
Instant now = Instant.now();
System.out.println(now);
System.out.printf("%23d toEpochMilli()%n", now.toEpochMilli());
System.out.printf("%26d toEpochMilli() * 1000 = a%n", now.toEpochMilli() * 1000L);
System.out.printf("%29d getNano()%n", now.getNano());
System.out.printf("%26d getNano() / 1000 = b%n", now.getNano() / 1000L);
System.out.printf("%26d a + b%n", now.toEpochMilli() * 1000L + now.getNano() / 1000L);
Вывод
2019-02-02T00:16:58.999999999Z
1549066618999 toEpochMilli()
1549066618999000 toEpochMilli() * 1000 = a
999999999 getNano()
999999 getNano() / 1000 = b
1549066619998999 a + b
Так, когда часы при переключении с x:58.999999999Z
на x:59.000000000Z
вы получаете:
2019-02-02T00:16:59.000000000Z
1549066619000 toEpochMilli()
1549066619000000 toEpochMilli() * 1000 = a
000000000 getNano()
000000 getNano() / 1000 = b
1549066619000000 a + b
Значение, равное 1 наносекунде позже, возвращает значение, которое на 998999 микросекунд раньше.
Расчетное значение работает с удвоенной скоростью и каждую секунду откатывается назад на 1 секунду.
Правильная формула (на Java):
Instant now = Instant.now();
return now.getEpochSecond() * 1000000L + now.getNano() / 1000L;