SlideShare una empresa de Scribd logo
1 de 106
Война
Данных
Кровавый Ынтерпрайз
наносит ответный удар
Виктор
Полищук
@alkovictor
Смысл? Что? Зачем?
99% проектов имеют проблемы
Большая доля этого отводится данным
Разработка постоянно усложняется
Часто проблему можно было предотвратить
Война данных: @alkovictor 3
Деньги, числа, арифметика
Идентификаторы
Текст и строки
Дата и время
Война данных: @alkovictor 4
Участие
Приветствуется
Деньги
Деньги Типы
Float и Double
Integer и Long
BigDecimal
Война данных: @alkovictor 7
Деньги Float и
Double
Хорошо
Встроенные типы
Большой диапазон значений
• Float: 1.4*10-45…3.4028235*10+38
• Double: 4.9*10-324…1.7976931348623157*10+308
Война данных: @alkovictor 8
Деньги Float и
Double
Беда
Обычно разработчики не знают как
вот это представлено в памяти:
• 𝑒 = 2.718281828459045
• π = 3.141592653589793
• tan
π
2
= 1.633123935319537𝑬16
Война данных: @alkovictor 9
Деньги Float и
Double
ЧЗХ #1
• = ?
Float: 0.6 + 0.1
• = ?
Double: 0.6 + 0.1
Война данных: @alkovictor 10
Деньги Float и
Double
ЧЗХ #1
• = 0.70000005
Float: 0.6 + 0.1
• = 0.7
Double: 0.6 + 0.1
Война данных: @alkovictor 11
Деньги Float и
Double
stackoverflow.com
Война данных: @alkovictor 12
Деньги Float и
Double
ЧЗХ #2
• = ?
Float: 0.2 + 0.1
• = ?
Double: 0.2 + 0.1
Война данных: @alkovictor 13
Деньги Float и
Double
ЧЗХ #2
• = 0.3
Float: 0.2 + 0.1
• = 0.30000000000000004
Double: 0.2 + 0.1
Война данных: @alkovictor 14
Деньги Float и
Double
Чё Внутри
Знак – плюс/минус
Экспонента – степень двойки
Мантисса – двоичное число
Война данных: @alkovictor 15
Деньги Float и
Double
Чё Внутри
Float (32 бита)
Double (64 бита)
Война данных: @alkovictor 16
1 8 23
1 11 52
Деньги Float и
Double
И Чё?
0.1f = [0]-[01111011]-[10011001100110011001101]
0.1f = + 2123-127 * (1 + 2-1 + 2-4 + 2-5 + 2-8 + 2-9 + 2-12 + …)
0.1f = 0.100000001490116119384765625
0.01f = [0]-[01111000]-[01000111101011100001010]
0.01f = 0.00999999977648258209228515625
Война данных: @alkovictor 17
Деньги Float и
Double
Пример
Война данных: @alkovictor 18
Деньги Float и
Double
ЧЗХ #3
+∞ = [0]-[11111111]-[00000000000000000000000]
-∞ = [1]-[11111111]-[00000000000000000000000]
NAN = [?]-[11111111]-[???????????????????????]
+0.0 = [0]-[00000000]-[00000000000000000000000]
-0.0 = [1]-[00000000]-[00000000000000000000000]
+0.0f == -0.0f?
Война данных: @alkovictor 19
Деньги Float и
Double
Чё Внутри
/**
* Get or create float value for the given float.
*
* @param d the float
* @return the value
*/
public static ValueFloat get(float d) {
if (d == 1.0F) {
return ONE;
} else if (d == 0.0F) {
// -0.0 == 0.0, and we want to return 0.0 for both
return ZERO;
}
return (ValueFloat) Value.cache(new ValueFloat(d));
} Война данных: @alkovictor 20
Деньги Float и
Double
Итог
Очень узкая область применения
Не очевидны
Не использовать
Забыть про существование
Война данных: @alkovictor 21
Деньги Integer и
Long
Хорошо
Встроенные типы
Целочисленная арифметика
•Нет деления на степень двойки
Война данных: @alkovictor 22
Деньги Integer и
Long
Как?
Храним деньги в «копейках»
Где-то храним «scale»
• например, как глобальную константу
Война данных: @alkovictor 23
Деньги Integer и
Long
Как?
«Scale» – это
N значащих
цифр после
запятой
Домножаем
или делим
на 10scale
Война данных: @alkovictor 24
Деньги Integer и
Long
ЧЗХ #1
•= ?
10(2) * 230(2) + 4(2)
Война данных: @alkovictor 25
Деньги Integer и
Long
ЧЗХ #1
•=0.1*2.3+0.04=27(2)
10(2) * 230(2) + 4(2)
Война данных: @alkovictor 26
Деньги Integer и
Long
Как Надо?
@Embeddable
public class Amount implements Serializable {
private int rate;
@Transient
private final int scale;
public Amount() {
scale = 6;
}
public Amount(int rate, int scale) {
this.scale = scale;
setRate(rate);
}
…
Война данных: @alkovictor 27
Деньги Integer и
Long
ЧЗХ #2
•= (int) ?
•= (long) ?
1.000000*0.150000
Война данных: @alkovictor 28
Деньги Integer и
Long
ЧЗХ #2
•= (int) -323855360
•= (long) 0.150000.000000
1.000000*0.150000
Война данных: @alkovictor 29
Деньги Integer и
Long
Итог
Лучше когда «scale» является частью значения
Лучше когда арифметика и сравнения просто работают
Лучше когда корректность гарантирована
Корректность почти всегда важнее скорости
Война данных: @alkovictor 30
Деньги BigDecimal Хорошо
Встроенный тип
Нет предыдущих проблем
Очень большой диапазон
Война данных: @alkovictor 31
Деньги BigDecimal ЧЗХ #1
•=?
1.divide(2)
Война данных: @alkovictor 32
Деньги BigDecimal ЧЗХ #1
•=0.5
1.divide(2)
Война данных: @alkovictor 33
Деньги BigDecimal ЧЗХ #2
•=?
2.divide(3)
Война данных: @alkovictor 34
Деньги BigDecimal ЧЗХ #2
•=ArithmeticException
2.divide(3)
Война данных: @alkovictor 35
Деньги BigDecimal ЧЗХ #2
•=0.666 или 0.667
2.divide(3, 3, ...)
Война данных: @alkovictor 36
Деньги BigDecimal ЧЗХ #3
• =?
1.divide(10).multiply(10).equals(1)
Война данных: @alkovictor 37
Деньги BigDecimal ЧЗХ #3
• = false
1.divide(10).multiply(10).equals(1)
Война данных: @alkovictor 38
Деньги BigDecimal ЧЗХ #4
• =?
BD.valueOf(0.1f).equals(new BD(0.1f))
Война данных: @alkovictor 39
Деньги BigDecimal ЧЗХ #4
• = false
BD.valueOf(0.1f).equals(new BD(0.1f))
Война данных: @alkovictor 40
Деньги BigDecimal ЧЗХ #5
Война данных: @alkovictor 41
BigDecimal i = ONE;
while (i.compareTo(TEN) < 0) {
i.add(ONE).multiply(i);
}
System.out.println(i);
Деньги BigDecimal ЧЗХ #5
Война данных: @alkovictor 42
41
ArithmeticException
Ничего
19
Деньги BigDecimal ЧЗХ #5
Война данных: @alkovictor 43
BigDecimal i = ONE;
while (i.compareTo(TEN) < 0) {
i.add(ONE).multiply(i);
}
System.out.println(i);
Деньги BigDecimal ЧЗХ #5
Война данных: @alkovictor 44
8
ArithmeticException
Ничего
10
Деньги BigDecimal ЧЗХ #5
Война данных: @alkovictor 45
BigDecimal i = ONE;
while (i.compareTo(TEN) < 0) {
i.add(ONE).multiply(i);
}
System.out.println(i);
Деньги BigDecimal Итог
Точность и значность известна
Арифметика и сравнения включены
Поддерживается в JDK, JDBC и т.д.
Неплохая производительность
Война данных: @alkovictor 46
Идентификаторы
Война данных: @alkovictor 47
ID Содержание
Integer и Long
UUID
Война данных: @alkovictor 48
ID Integer и
Long
Integer и Long – конечные типы
Иногда они переполняются
Они в два раза меньше, чем мы думаем
Война данных: @alkovictor 49
ID Integer и
Long
Пример
Война данных: @alkovictor 50
ID Integer и
Long
Пример
Война данных: @alkovictor 51
ID Integer и
Long
Нежданчик
«Некоторые» языки не умееют работать с
64-битными целыми
Кроме того, «некоторые» языки работают
со специальными 32-битными целыми
Война данных: @alkovictor 52
ID Integer и
Long
Итог
Разница между DB и API идентификаторами
Если не на 99.9% уверен
• Используй целочисленные ключи в DB
• Используй строковые идентификаторы для API
• Не используй 32- битные типы
Война данных: @alkovictor 53
ID UUID Хорошо
Генерирует ID локально
Довольно мал: 128 бит (16 байт)
Очень маленькая вероятность коллизии
• 1 на 2.71 квинтиллионов (1018)
• Вероятность эквивалентна встрече 180 мужчин подряд
Война данных: @alkovictor 54
ID UUID Ну такое
Не гарантированно глобально уникальны
Могут быть источником проблем с производительностью
Существует несколько версий с разной степени полезности
Странно, но RDBMS редко поддерживают UUID/GUID типы
Война данных: @alkovictor 55
ID UUID Чё внутри
High long
32
time_low
16
time_mid
4
version
12
time_hi
Low long
4
variant
12
clock_seq
48
node
Война данных: @alkovictor 56
ID UUID Чё внутри
High long
32
random
16
random
4
version
12
random
Low long
4
variant
12
clock_seq
48
random
Война данных: @alkovictor 57
ID UUID Пример
$ uuidgen
0c8aa0f6-9f6f-4fad-9662-1b683f2f4a0d
$ uuidgen
1ee09695-3a04-4e7a-8bab-e67dabc4b5a2
$ uuidgen -t
3770f4d0-88b3-11e6-bba6-005056bb68cb
$ uuidgen -t
3b14dd54-88b3-11e6-8c53-005056bb68cb
Война данных: @alkovictor 58
ID UUID v4
Зависит от генератора энтропии
Виртуальные машины
Контейнеры
Война данных: @alkovictor 59
ID Итог
Используйте внешнее строковое представление (API)
Внутреннее представление должно быть:
• DB счетчик (Long/BigInteger)
• UUID + DB счетчик (Long/BigInteger)
• UUID
• Twitter Snowflake (Long) – не развивается
• *Flake (128 bit)
Война данных: @alkovictor 60
Строки
Строки Содержание
Кодировка строк в Java
JDBC драйвера и DB типы
Война данных: @alkovictor 62
Строки Кодировка
Java использует UTF-16 для строк
Кодовая таблица UTF-16: 0x0000..0x10FFFF
Строки используют char[] (byte[] in JDK9)
Возможные значения char: 0x0000..0xFFFF
Война данных: @alkovictor 63
Строки Кодировка ЧЗХ #1
Как представить символы
0x100000..0x10FFFF
используя char?
Война данных: @alkovictor 64
Строки Кодировка ЧЗХ #1
Определим «суррогатный» диапазон: 0xD800..0xDFFF [0x800] [2048]
Поделим его пополам:
• «High»: 0xD800..0xDBFF [0x400] [1024]
• «Low»: 0xDC00..0xDFFF [0x400] [1024]
Используем пары (High;Low) для получения недостающих символов
...
PROFIT!!!
Война данных: @alkovictor 65
Строки Кодировка ЧЗХ #2
Война данных: @alkovictor 66
String x = new String(new char[]{
'z',0xD801,0xDC05,'a','b','c'
});
System.out.println(x.length());
System.out.println(x);
System.out.println(x.substring(0,2));
System.out.println(x.substring(2));
Строки Кодировка ЧЗХ #2
Война данных: @alkovictor 67
6
z𐐅abc
z?
?abc
Строки Кодировка Решение
Война данных: @alkovictor 68
Character.isLowSurrogate(...);
Character.isHighSurrogate(...);
Строки Кодировка Итог
Хорошего решения нет
Надо об этом помнить
Война данных: @alkovictor 69
Строки JDBC vs DB
Отображение JDBC типов на DB
Некоторые примеры
BLOB или CLOB
Несовместимые кодировки
Война данных: @alkovictor 70
Строки JDBC vs DB Отображение
public enum JDBCType implements SQLType {
CHAR(Types.CHAR),
VARCHAR(Types.VARCHAR),
LONGVARCHAR(Types.LONGVARCHAR),
...
BLOB(Types.BLOB),
CLOB(Types.CLOB),
...
NCHAR(Types.NCHAR),
NVARCHAR(Types.NVARCHAR),
LONGNVARCHAR(Types.LONGNVARCHAR),
NCLOB(Types.NCLOB), Война данных: @alkovictor 71
Строки JDBC vs DB BLOB
Война данных: @alkovictor 72
BLOB – это не текст
И никогда не будет
Строки JDBC vs DB BLOB/CLOB
Binary Large OBject
• Массив байт
Character Large OBject
• Массив символов в «некоторой» кодировке
Война данных: @alkovictor 73
Строки JDBC vs DB Отображение
public enum JDBCType implements SQLType {
CHAR(Types.CHAR),
VARCHAR(Types.VARCHAR),
LONGVARCHAR(Types.LONGVARCHAR),
...
CLOB(Types.CLOB),
...
NCHAR(Types.NCHAR),
NVARCHAR(Types.NVARCHAR),
LONGNVARCHAR(Types.LONGNVARCHAR),
NCLOB(Types.NCLOB),
Война данных: @alkovictor 74
Строки JDBC vs DB
CHAR и
VARCHAR
Война данных: @alkovictor 75
Тип Oracle MySQL MS SQL
CHAR 2000 b 255 char 8000 b
VARCHAR 4000 b 255 char
65535 b
8000 b
~ 2 Gb
Строки JDBC vs DB Чё внутри?
setStringInternal(int var1,String var2) throws SQLException {
...
int var6 = var2 != null?var2.length():0;
...
if(var6 <= this.maxVcsCharsSql) {
this.basicBindString(var1, var2);
} else if(var6 <= this.maxStreamNCharsSql) {
this.setStringForClobCritical(var1, var2);
} else {
this.setStringForClobCritical(var1, var2);
}
Война данных: @alkovictor 76
Строки JDBC vs DB CHAR/NCHAR
CHAR, VARCHAR, CLOB…
• Использует кодировку DB
NCHAR, NVARCHAR, NCLOB…
• Использует указанную (национальную)
кодировку
Война данных: @alkovictor 77
Строки JDBC vs DB Совместимость
Иногда у вас нет проблем с кодировками
Иногда «умный» драйвер все портит
Иногда кодировки несовместимы
Используйте Unicode семейство в DB
Война данных: @alkovictor 78
Строки JDBC vs DB Итог
Используй Unicode кодировку DB
Если уже поздно пользуйся N* DB типами
Не храни текст как BLOB
Знай специфику драйвера и DB
Символ – это не байт, и часто даже не два
Война данных: @alkovictor 79
Дата и Время
Дата Содержание
Базис: Instant и Date
DST и високосная магия
Временные зоны
Война данных: @alkovictor 81
Дата Базис Инфо
Instant
• Представляет некое временное событие отсчитаное от
точки отсчета в равномерных интервалах
DateTime
• Кортеж, неравномерных интервалов приятных для
человеческого восприятия, чаще всего привязанных к
циклам солнца и/или луны. Год-месяц-день и т.д.
Война данных: @alkovictor 82
Дата Базис И Чё?
Instant
• это «абсолютное» земное время
DateTime
• это представление времени, конвертируемое
в Instant, но не всегда однозначно.
Война данных: @alkovictor 83
Дата Базис Итог
Instant
• используй если важна причинность, и если
даже [милли-]секунда важна
DateTime
• используй во всех остальных случаях
Война данных: @alkovictor 84
Дата DST и
Магия
Пропущеные и лишние часы
«Високосные» секунды
Война данных: @alkovictor 85
Дата DST и
Магия
Вычисления
24 часа в дне
60 минут в часе
60 секунд в минуте
Итого: 24 * 60 * 60 * 1000 мс/день
Война данных: @alkovictor 86
Дата DST и
Магия ЧЗХ #1
• 23 часа (нет 26.03.2017 03:00-04:00)
26.03.2017-27.03.2017 EET
• 25 часа (два 29.10.2017 03:00-04:00)
29.10.2017-30.10.2017 EET
Война данных: @alkovictor 87
Дата DST и
Магия ЧЗХ #2
• 24 часа
31.12.2016-01.01.2017 EET
• 24 часа и 1 секунда
01.01.2017-02.01.2017 EET
Война данных: @alkovictor 88
Дата DST и
Магия
Високосные
секунды
Было: 31.12.2016 23:59:60 (UTC)
Пока нет точного графика
Виновата Земля, Луна, Солнце и т.д.
Разработчики тоже виноваты
Война данных: @alkovictor 89
Дата Зоны
Временные зоны
• позволяют работать с локальным временем
Правила конвертации
• позволяют преобразовывать в Instant
• позволяют преобразовывать в другие зоны
Война данных: @alkovictor 90
Дата Зоны Запись
Война данных: @alkovictor 91
PreparedStatement.setTimestamp(
1,
new Timestamp(...),
Calendar.getInstance(
TimeZone.getTimeZone("UTC")
)
);
Дата Зоны Чтение
Война данных: @alkovictor 92
Timestamp ts = ResultSet.getTimestamp(
1,
Calendar.getInstance(
TimeZone.getTimeZone("...")
)
);
Дата Зоны ЧЗХ #3
Война данных: @alkovictor 93
• UTC =?
• Киев =?
• Брюссель =?
• *BD* =?
Сохранили 2017-03-26 12:00+00:00
Дата Зоны ЧЗХ #3
Война данных: @alkovictor 94
• UTC = 2017-03-26 15:00+03:00 [ 0]
• Киев = 2017-03-26 12:00+03:00 [-3]
• Брюссель = 2017-03-26 13:00+03:00 [-2]
• *BD* = 2017-03-26 12:00:00.0
Сохранили 2017-03-26 12:00+00:00
Дата Зоны ЧЗХ #3
Война данных: @alkovictor 95
Retrieves the value of the designated column in the current
row of this ResultSet object as a java.sql.Timestamp object
in the Java programming language. This method uses the
given calendar to construct an appropriate millisecond value
for the timestamp if the underlying database does not store
timezone information.
• columnIndex - the first column is 1, the second is 2, ...
• cal - the java.util.Calendar object to use in constructing the timestamp
Дата Зоны А если
надо?
TIMESTAMP
TIMESTAMP WITH TIME ZONE
DATETIMEOFFSET
Война данных: @alkovictor 96
Дата Зоны ЧЗХ #4
Война данных: @alkovictor 97
• MS SQL v4 =?
• Oracle v10 =?
• Oracle v12 =?
Сохранили 2017-03-26 12:00+00:00
Дата Зоны ЧЗХ #4
Война данных: @alkovictor 98
• MS SQL v4 = 2017-03-26 12:00+00:00
• Oracle v10 = 2017-03-26 12:00+00:00
• Oracle v12 = 2017-03-26 12:00+03:00
Сохранили 2017-03-26 12:00+00:00
Дата Зоны oracle.sql.TIMESTAMP
Война данных: @alkovictor 99
public static byte[] toBytes(Timestamp var0, Calendar var1) {
if (var0 == null) { return null; }
int var2 = var0.getNanos();
byte[] var3 = var2 == 0 ? new byte[7] : new byte[11];
Calendar var4 = var1 == null ? Calendar.getInstance() : Calendar.getInstance(var1.getTimeZone());
var4.setTime(var0);
int var5 = getOracleYear(var4);
var3[0] = (byte) (var5 / 100 + 100);
var3[1] = (byte) (var5 % 100 + 100);
var3[2] = (byte) (var4.get(2) + 1); // Calendar.MONTH
var3[3] = (byte) var4.get(5); // Calendar.DATE (DAY_OF_MONTH)
var3[4] = (byte) (var4.get(11) + 1); // Calendar.HOUR_OF_DAY
var3[5] = (byte) (var4.get(12) + 1); // Calendar.MINUTE
var3[6] = (byte) (var4.get(13) + 1); // Calendar.SECOND
if (var2 != 0) {
var3[7] = (byte) (var2 >> 24);
var3[8] = (byte) (var2 >> 16 & 255);
var3[9] = (byte) (var2 >> 8 & 255);
var3[10] = (byte) (var2 & 255);
}
return var3;
}
Дата Зоны ЧЗХ #4
Война данных: @alkovictor 100
• MS SQL v4 = 2017-03-26 12:00+00:00
• Oracle v10 = 2017-03-26 12:00+00:00
• Oracle v12 = 2017-03-26 12:00+00:00
Сохранили 2017-03-26 12:00+00:00
Дата Зоны Что делать?
Война данных: @alkovictor 101
Использовать только UTC
Использовать “странный” API
• void setObject(int, Object, int, int)
Использовать java.time API или Calendar
• ZonedDateTime and etc
Не верить имплементаторам JDBC
Дата Зоны Вопросы
JavaScript клиент с непонятной зоной
Java сервер с +03:00 зоной
Как передавать даты?
Война данных: @alkovictor 102
Дата Зоны Ответы
Дата не определена в спецификации JSON
Long – это плохая идея для JavaScript
String как ISO 8601 меньшее зло
Война данных: @alkovictor 103
Дата Зоны Итог
Используй единую временную зону
Тестируй драйвер на ожидаемое поведение
• Например: https://github.com/victor-cr/jdbc-test
*Не используй setTimestamp(…) для Instant
Публикуй дату как строку в JSON API
Война данных: @alkovictor 104
Дата Итог
Используй UTC как можно чаще
Помни про разницу даты и Instant
Работай с датами по закону Мерфи
24*60*60*1000 – это небезопасное упрощение
Используй специальные библиотеки для работы с датами
Война данных: @alkovictor 105
Спасибо

Más contenido relacionado

Similar a Data Wars: The Bloody Enterprise strikes back

SECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кодаSECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
Конференция разработчиков программного обеспечения SECON'2014
 
Методы вставки палок в колеса ботмастерам: ботнет Kelihos
Методы вставки палок  в колеса ботмастерам:  ботнет KelihosМетоды вставки палок  в колеса ботмастерам:  ботнет Kelihos
Методы вставки палок в колеса ботмастерам: ботнет Kelihos
Positive Hack Days
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
Computer Science Club
 
MySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации баговMySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации багов
Sveta Smirnova
 
«Introduction to malware reverse engineering» by Sergey Kharyuk aka ximerus
 «Introduction to malware reverse engineering» by Sergey Kharyuk aka ximerus «Introduction to malware reverse engineering» by Sergey Kharyuk aka ximerus
«Introduction to malware reverse engineering» by Sergey Kharyuk aka ximerus
0xdec0de
 
«Introduction to malware reverse engineering» by Sergey Kharyuk
«Introduction to malware reverse engineering» by Sergey Kharyuk«Introduction to malware reverse engineering» by Sergey Kharyuk
«Introduction to malware reverse engineering» by Sergey Kharyuk
0xdec0de
 

Similar a Data Wars: The Bloody Enterprise strikes back (20)

Поговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийПоговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложений
 
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
 
Ликбез • Блокчейн (Level 1)
Ликбез • Блокчейн (Level 1)Ликбез • Блокчейн (Level 1)
Ликбез • Блокчейн (Level 1)
 
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кодаSECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
 
Методы вставки палок в колеса ботмастерам: ботнет Kelihos
Методы вставки палок  в колеса ботмастерам:  ботнет KelihosМетоды вставки палок  в колеса ботмастерам:  ботнет Kelihos
Методы вставки палок в колеса ботмастерам: ботнет Kelihos
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
 
200 open source проектов спустя: опыт статического анализа исходного кода
200 open source проектов спустя:опыт статического анализа исходного кода200 open source проектов спустя:опыт статического анализа исходного кода
200 open source проектов спустя: опыт статического анализа исходного кода
 
Dsl for c++
Dsl for c++Dsl for c++
Dsl for c++
 
Компилируемые в реальном времени DSL для С++
Компилируемые в реальном времени DSL для С++Компилируемые в реальном времени DSL для С++
Компилируемые в реальном времени DSL для С++
 
Паттерны 64-битных ошибок в играх
Паттерны 64-битных ошибок в играхПаттерны 64-битных ошибок в играх
Паттерны 64-битных ошибок в играх
 
Python и Cython
Python и CythonPython и Cython
Python и Cython
 
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
 
Convert this: peculiarities of cross-platform mobile game development at Vizor
Convert this: peculiarities of cross-platform mobile game development at VizorConvert this: peculiarities of cross-platform mobile game development at Vizor
Convert this: peculiarities of cross-platform mobile game development at Vizor
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
MySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации баговMySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации багов
 
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
 
SECON'2016. Чубарь Алексей, Мобильные грабли Unity
SECON'2016. Чубарь Алексей, Мобильные грабли UnitySECON'2016. Чубарь Алексей, Мобильные грабли Unity
SECON'2016. Чубарь Алексей, Мобильные грабли Unity
 
«Introduction to malware reverse engineering» by Sergey Kharyuk aka ximerus
 «Introduction to malware reverse engineering» by Sergey Kharyuk aka ximerus «Introduction to malware reverse engineering» by Sergey Kharyuk aka ximerus
«Introduction to malware reverse engineering» by Sergey Kharyuk aka ximerus
 
«Introduction to malware reverse engineering» by Sergey Kharyuk
«Introduction to malware reverse engineering» by Sergey Kharyuk«Introduction to malware reverse engineering» by Sergey Kharyuk
«Introduction to malware reverse engineering» by Sergey Kharyuk
 

Más de Victor_Cr

Jboss drools expert (ru)
Jboss drools expert (ru)Jboss drools expert (ru)
Jboss drools expert (ru)
Victor_Cr
 
JEEConf JBoss Drools
JEEConf JBoss DroolsJEEConf JBoss Drools
JEEConf JBoss Drools
Victor_Cr
 
JBoss Drools
JBoss DroolsJBoss Drools
JBoss Drools
Victor_Cr
 
Club of anonimous developers "Refactoring: Legacy code"
Club of anonimous developers "Refactoring: Legacy code"Club of anonimous developers "Refactoring: Legacy code"
Club of anonimous developers "Refactoring: Legacy code"
Victor_Cr
 

Más de Victor_Cr (16)

Data Wars: The Bloody Enterprise strikes back
Data Wars: The Bloody Enterprise strikes backData Wars: The Bloody Enterprise strikes back
Data Wars: The Bloody Enterprise strikes back
 
Type War: Weak vs Strong [JEEConf 2016]
Type War: Weak vs Strong [JEEConf 2016]Type War: Weak vs Strong [JEEConf 2016]
Type War: Weak vs Strong [JEEConf 2016]
 
Types: Weak/Duck/Optional vs Strong/Strict. Let the War Begin!
Types: Weak/Duck/Optional vs Strong/Strict. Let the War Begin!Types: Weak/Duck/Optional vs Strong/Strict. Let the War Begin!
Types: Weak/Duck/Optional vs Strong/Strict. Let the War Begin!
 
Types: Weak/Duck/Optional vs Strong/Strict. Let the War Begin!
Types: Weak/Duck/Optional vs Strong/Strict. Let the War Begin!Types: Weak/Duck/Optional vs Strong/Strict. Let the War Begin!
Types: Weak/Duck/Optional vs Strong/Strict. Let the War Begin!
 
Legacy: как победить в гонке (Joker)
Legacy: как победить в гонке (Joker)Legacy: как победить в гонке (Joker)
Legacy: как победить в гонке (Joker)
 
Web-application I’ve always dreamt of (Kharkiv)
Web-application I’ve always dreamt of (Kharkiv)Web-application I’ve always dreamt of (Kharkiv)
Web-application I’ve always dreamt of (Kharkiv)
 
Web application I have always dreamt of (Lviv)
Web application I have always dreamt of (Lviv)Web application I have always dreamt of (Lviv)
Web application I have always dreamt of (Lviv)
 
Web application I have always dreamt of
Web application I have always dreamt ofWeb application I have always dreamt of
Web application I have always dreamt of
 
Legacy projects: how to win the race
Legacy projects: how to win the raceLegacy projects: how to win the race
Legacy projects: how to win the race
 
Legacy projects: how to win the race
Legacy projects: how to win the raceLegacy projects: how to win the race
Legacy projects: how to win the race
 
Jboss drools expert (ru)
Jboss drools expert (ru)Jboss drools expert (ru)
Jboss drools expert (ru)
 
JEEConf WEB
JEEConf WEBJEEConf WEB
JEEConf WEB
 
JEEConf JBoss Drools
JEEConf JBoss DroolsJEEConf JBoss Drools
JEEConf JBoss Drools
 
JBoss Drools
JBoss DroolsJBoss Drools
JBoss Drools
 
XPDays Ukraine: Legacy
XPDays Ukraine: LegacyXPDays Ukraine: Legacy
XPDays Ukraine: Legacy
 
Club of anonimous developers "Refactoring: Legacy code"
Club of anonimous developers "Refactoring: Legacy code"Club of anonimous developers "Refactoring: Legacy code"
Club of anonimous developers "Refactoring: Legacy code"
 

Data Wars: The Bloody Enterprise strikes back

  • 3. Смысл? Что? Зачем? 99% проектов имеют проблемы Большая доля этого отводится данным Разработка постоянно усложняется Часто проблему можно было предотвратить Война данных: @alkovictor 3
  • 4. Деньги, числа, арифметика Идентификаторы Текст и строки Дата и время Война данных: @alkovictor 4
  • 7. Деньги Типы Float и Double Integer и Long BigDecimal Война данных: @alkovictor 7
  • 8. Деньги Float и Double Хорошо Встроенные типы Большой диапазон значений • Float: 1.4*10-45…3.4028235*10+38 • Double: 4.9*10-324…1.7976931348623157*10+308 Война данных: @alkovictor 8
  • 9. Деньги Float и Double Беда Обычно разработчики не знают как вот это представлено в памяти: • 𝑒 = 2.718281828459045 • π = 3.141592653589793 • tan π 2 = 1.633123935319537𝑬16 Война данных: @alkovictor 9
  • 10. Деньги Float и Double ЧЗХ #1 • = ? Float: 0.6 + 0.1 • = ? Double: 0.6 + 0.1 Война данных: @alkovictor 10
  • 11. Деньги Float и Double ЧЗХ #1 • = 0.70000005 Float: 0.6 + 0.1 • = 0.7 Double: 0.6 + 0.1 Война данных: @alkovictor 11
  • 13. Деньги Float и Double ЧЗХ #2 • = ? Float: 0.2 + 0.1 • = ? Double: 0.2 + 0.1 Война данных: @alkovictor 13
  • 14. Деньги Float и Double ЧЗХ #2 • = 0.3 Float: 0.2 + 0.1 • = 0.30000000000000004 Double: 0.2 + 0.1 Война данных: @alkovictor 14
  • 15. Деньги Float и Double Чё Внутри Знак – плюс/минус Экспонента – степень двойки Мантисса – двоичное число Война данных: @alkovictor 15
  • 16. Деньги Float и Double Чё Внутри Float (32 бита) Double (64 бита) Война данных: @alkovictor 16 1 8 23 1 11 52
  • 17. Деньги Float и Double И Чё? 0.1f = [0]-[01111011]-[10011001100110011001101] 0.1f = + 2123-127 * (1 + 2-1 + 2-4 + 2-5 + 2-8 + 2-9 + 2-12 + …) 0.1f = 0.100000001490116119384765625 0.01f = [0]-[01111000]-[01000111101011100001010] 0.01f = 0.00999999977648258209228515625 Война данных: @alkovictor 17
  • 19. Деньги Float и Double ЧЗХ #3 +∞ = [0]-[11111111]-[00000000000000000000000] -∞ = [1]-[11111111]-[00000000000000000000000] NAN = [?]-[11111111]-[???????????????????????] +0.0 = [0]-[00000000]-[00000000000000000000000] -0.0 = [1]-[00000000]-[00000000000000000000000] +0.0f == -0.0f? Война данных: @alkovictor 19
  • 20. Деньги Float и Double Чё Внутри /** * Get or create float value for the given float. * * @param d the float * @return the value */ public static ValueFloat get(float d) { if (d == 1.0F) { return ONE; } else if (d == 0.0F) { // -0.0 == 0.0, and we want to return 0.0 for both return ZERO; } return (ValueFloat) Value.cache(new ValueFloat(d)); } Война данных: @alkovictor 20
  • 21. Деньги Float и Double Итог Очень узкая область применения Не очевидны Не использовать Забыть про существование Война данных: @alkovictor 21
  • 22. Деньги Integer и Long Хорошо Встроенные типы Целочисленная арифметика •Нет деления на степень двойки Война данных: @alkovictor 22
  • 23. Деньги Integer и Long Как? Храним деньги в «копейках» Где-то храним «scale» • например, как глобальную константу Война данных: @alkovictor 23
  • 24. Деньги Integer и Long Как? «Scale» – это N значащих цифр после запятой Домножаем или делим на 10scale Война данных: @alkovictor 24
  • 25. Деньги Integer и Long ЧЗХ #1 •= ? 10(2) * 230(2) + 4(2) Война данных: @alkovictor 25
  • 26. Деньги Integer и Long ЧЗХ #1 •=0.1*2.3+0.04=27(2) 10(2) * 230(2) + 4(2) Война данных: @alkovictor 26
  • 27. Деньги Integer и Long Как Надо? @Embeddable public class Amount implements Serializable { private int rate; @Transient private final int scale; public Amount() { scale = 6; } public Amount(int rate, int scale) { this.scale = scale; setRate(rate); } … Война данных: @alkovictor 27
  • 28. Деньги Integer и Long ЧЗХ #2 •= (int) ? •= (long) ? 1.000000*0.150000 Война данных: @alkovictor 28
  • 29. Деньги Integer и Long ЧЗХ #2 •= (int) -323855360 •= (long) 0.150000.000000 1.000000*0.150000 Война данных: @alkovictor 29
  • 30. Деньги Integer и Long Итог Лучше когда «scale» является частью значения Лучше когда арифметика и сравнения просто работают Лучше когда корректность гарантирована Корректность почти всегда важнее скорости Война данных: @alkovictor 30
  • 31. Деньги BigDecimal Хорошо Встроенный тип Нет предыдущих проблем Очень большой диапазон Война данных: @alkovictor 31
  • 32. Деньги BigDecimal ЧЗХ #1 •=? 1.divide(2) Война данных: @alkovictor 32
  • 33. Деньги BigDecimal ЧЗХ #1 •=0.5 1.divide(2) Война данных: @alkovictor 33
  • 34. Деньги BigDecimal ЧЗХ #2 •=? 2.divide(3) Война данных: @alkovictor 34
  • 35. Деньги BigDecimal ЧЗХ #2 •=ArithmeticException 2.divide(3) Война данных: @alkovictor 35
  • 36. Деньги BigDecimal ЧЗХ #2 •=0.666 или 0.667 2.divide(3, 3, ...) Война данных: @alkovictor 36
  • 37. Деньги BigDecimal ЧЗХ #3 • =? 1.divide(10).multiply(10).equals(1) Война данных: @alkovictor 37
  • 38. Деньги BigDecimal ЧЗХ #3 • = false 1.divide(10).multiply(10).equals(1) Война данных: @alkovictor 38
  • 39. Деньги BigDecimal ЧЗХ #4 • =? BD.valueOf(0.1f).equals(new BD(0.1f)) Война данных: @alkovictor 39
  • 40. Деньги BigDecimal ЧЗХ #4 • = false BD.valueOf(0.1f).equals(new BD(0.1f)) Война данных: @alkovictor 40
  • 41. Деньги BigDecimal ЧЗХ #5 Война данных: @alkovictor 41 BigDecimal i = ONE; while (i.compareTo(TEN) < 0) { i.add(ONE).multiply(i); } System.out.println(i);
  • 42. Деньги BigDecimal ЧЗХ #5 Война данных: @alkovictor 42 41 ArithmeticException Ничего 19
  • 43. Деньги BigDecimal ЧЗХ #5 Война данных: @alkovictor 43 BigDecimal i = ONE; while (i.compareTo(TEN) < 0) { i.add(ONE).multiply(i); } System.out.println(i);
  • 44. Деньги BigDecimal ЧЗХ #5 Война данных: @alkovictor 44 8 ArithmeticException Ничего 10
  • 45. Деньги BigDecimal ЧЗХ #5 Война данных: @alkovictor 45 BigDecimal i = ONE; while (i.compareTo(TEN) < 0) { i.add(ONE).multiply(i); } System.out.println(i);
  • 46. Деньги BigDecimal Итог Точность и значность известна Арифметика и сравнения включены Поддерживается в JDK, JDBC и т.д. Неплохая производительность Война данных: @alkovictor 46
  • 48. ID Содержание Integer и Long UUID Война данных: @alkovictor 48
  • 49. ID Integer и Long Integer и Long – конечные типы Иногда они переполняются Они в два раза меньше, чем мы думаем Война данных: @alkovictor 49
  • 50. ID Integer и Long Пример Война данных: @alkovictor 50
  • 51. ID Integer и Long Пример Война данных: @alkovictor 51
  • 52. ID Integer и Long Нежданчик «Некоторые» языки не умееют работать с 64-битными целыми Кроме того, «некоторые» языки работают со специальными 32-битными целыми Война данных: @alkovictor 52
  • 53. ID Integer и Long Итог Разница между DB и API идентификаторами Если не на 99.9% уверен • Используй целочисленные ключи в DB • Используй строковые идентификаторы для API • Не используй 32- битные типы Война данных: @alkovictor 53
  • 54. ID UUID Хорошо Генерирует ID локально Довольно мал: 128 бит (16 байт) Очень маленькая вероятность коллизии • 1 на 2.71 квинтиллионов (1018) • Вероятность эквивалентна встрече 180 мужчин подряд Война данных: @alkovictor 54
  • 55. ID UUID Ну такое Не гарантированно глобально уникальны Могут быть источником проблем с производительностью Существует несколько версий с разной степени полезности Странно, но RDBMS редко поддерживают UUID/GUID типы Война данных: @alkovictor 55
  • 56. ID UUID Чё внутри High long 32 time_low 16 time_mid 4 version 12 time_hi Low long 4 variant 12 clock_seq 48 node Война данных: @alkovictor 56
  • 57. ID UUID Чё внутри High long 32 random 16 random 4 version 12 random Low long 4 variant 12 clock_seq 48 random Война данных: @alkovictor 57
  • 58. ID UUID Пример $ uuidgen 0c8aa0f6-9f6f-4fad-9662-1b683f2f4a0d $ uuidgen 1ee09695-3a04-4e7a-8bab-e67dabc4b5a2 $ uuidgen -t 3770f4d0-88b3-11e6-bba6-005056bb68cb $ uuidgen -t 3b14dd54-88b3-11e6-8c53-005056bb68cb Война данных: @alkovictor 58
  • 59. ID UUID v4 Зависит от генератора энтропии Виртуальные машины Контейнеры Война данных: @alkovictor 59
  • 60. ID Итог Используйте внешнее строковое представление (API) Внутреннее представление должно быть: • DB счетчик (Long/BigInteger) • UUID + DB счетчик (Long/BigInteger) • UUID • Twitter Snowflake (Long) – не развивается • *Flake (128 bit) Война данных: @alkovictor 60
  • 62. Строки Содержание Кодировка строк в Java JDBC драйвера и DB типы Война данных: @alkovictor 62
  • 63. Строки Кодировка Java использует UTF-16 для строк Кодовая таблица UTF-16: 0x0000..0x10FFFF Строки используют char[] (byte[] in JDK9) Возможные значения char: 0x0000..0xFFFF Война данных: @alkovictor 63
  • 64. Строки Кодировка ЧЗХ #1 Как представить символы 0x100000..0x10FFFF используя char? Война данных: @alkovictor 64
  • 65. Строки Кодировка ЧЗХ #1 Определим «суррогатный» диапазон: 0xD800..0xDFFF [0x800] [2048] Поделим его пополам: • «High»: 0xD800..0xDBFF [0x400] [1024] • «Low»: 0xDC00..0xDFFF [0x400] [1024] Используем пары (High;Low) для получения недостающих символов ... PROFIT!!! Война данных: @alkovictor 65
  • 66. Строки Кодировка ЧЗХ #2 Война данных: @alkovictor 66 String x = new String(new char[]{ 'z',0xD801,0xDC05,'a','b','c' }); System.out.println(x.length()); System.out.println(x); System.out.println(x.substring(0,2)); System.out.println(x.substring(2));
  • 67. Строки Кодировка ЧЗХ #2 Война данных: @alkovictor 67 6 z𐐅abc z? ?abc
  • 68. Строки Кодировка Решение Война данных: @alkovictor 68 Character.isLowSurrogate(...); Character.isHighSurrogate(...);
  • 69. Строки Кодировка Итог Хорошего решения нет Надо об этом помнить Война данных: @alkovictor 69
  • 70. Строки JDBC vs DB Отображение JDBC типов на DB Некоторые примеры BLOB или CLOB Несовместимые кодировки Война данных: @alkovictor 70
  • 71. Строки JDBC vs DB Отображение public enum JDBCType implements SQLType { CHAR(Types.CHAR), VARCHAR(Types.VARCHAR), LONGVARCHAR(Types.LONGVARCHAR), ... BLOB(Types.BLOB), CLOB(Types.CLOB), ... NCHAR(Types.NCHAR), NVARCHAR(Types.NVARCHAR), LONGNVARCHAR(Types.LONGNVARCHAR), NCLOB(Types.NCLOB), Война данных: @alkovictor 71
  • 72. Строки JDBC vs DB BLOB Война данных: @alkovictor 72 BLOB – это не текст И никогда не будет
  • 73. Строки JDBC vs DB BLOB/CLOB Binary Large OBject • Массив байт Character Large OBject • Массив символов в «некоторой» кодировке Война данных: @alkovictor 73
  • 74. Строки JDBC vs DB Отображение public enum JDBCType implements SQLType { CHAR(Types.CHAR), VARCHAR(Types.VARCHAR), LONGVARCHAR(Types.LONGVARCHAR), ... CLOB(Types.CLOB), ... NCHAR(Types.NCHAR), NVARCHAR(Types.NVARCHAR), LONGNVARCHAR(Types.LONGNVARCHAR), NCLOB(Types.NCLOB), Война данных: @alkovictor 74
  • 75. Строки JDBC vs DB CHAR и VARCHAR Война данных: @alkovictor 75 Тип Oracle MySQL MS SQL CHAR 2000 b 255 char 8000 b VARCHAR 4000 b 255 char 65535 b 8000 b ~ 2 Gb
  • 76. Строки JDBC vs DB Чё внутри? setStringInternal(int var1,String var2) throws SQLException { ... int var6 = var2 != null?var2.length():0; ... if(var6 <= this.maxVcsCharsSql) { this.basicBindString(var1, var2); } else if(var6 <= this.maxStreamNCharsSql) { this.setStringForClobCritical(var1, var2); } else { this.setStringForClobCritical(var1, var2); } Война данных: @alkovictor 76
  • 77. Строки JDBC vs DB CHAR/NCHAR CHAR, VARCHAR, CLOB… • Использует кодировку DB NCHAR, NVARCHAR, NCLOB… • Использует указанную (национальную) кодировку Война данных: @alkovictor 77
  • 78. Строки JDBC vs DB Совместимость Иногда у вас нет проблем с кодировками Иногда «умный» драйвер все портит Иногда кодировки несовместимы Используйте Unicode семейство в DB Война данных: @alkovictor 78
  • 79. Строки JDBC vs DB Итог Используй Unicode кодировку DB Если уже поздно пользуйся N* DB типами Не храни текст как BLOB Знай специфику драйвера и DB Символ – это не байт, и часто даже не два Война данных: @alkovictor 79
  • 81. Дата Содержание Базис: Instant и Date DST и високосная магия Временные зоны Война данных: @alkovictor 81
  • 82. Дата Базис Инфо Instant • Представляет некое временное событие отсчитаное от точки отсчета в равномерных интервалах DateTime • Кортеж, неравномерных интервалов приятных для человеческого восприятия, чаще всего привязанных к циклам солнца и/или луны. Год-месяц-день и т.д. Война данных: @alkovictor 82
  • 83. Дата Базис И Чё? Instant • это «абсолютное» земное время DateTime • это представление времени, конвертируемое в Instant, но не всегда однозначно. Война данных: @alkovictor 83
  • 84. Дата Базис Итог Instant • используй если важна причинность, и если даже [милли-]секунда важна DateTime • используй во всех остальных случаях Война данных: @alkovictor 84
  • 85. Дата DST и Магия Пропущеные и лишние часы «Високосные» секунды Война данных: @alkovictor 85
  • 86. Дата DST и Магия Вычисления 24 часа в дне 60 минут в часе 60 секунд в минуте Итого: 24 * 60 * 60 * 1000 мс/день Война данных: @alkovictor 86
  • 87. Дата DST и Магия ЧЗХ #1 • 23 часа (нет 26.03.2017 03:00-04:00) 26.03.2017-27.03.2017 EET • 25 часа (два 29.10.2017 03:00-04:00) 29.10.2017-30.10.2017 EET Война данных: @alkovictor 87
  • 88. Дата DST и Магия ЧЗХ #2 • 24 часа 31.12.2016-01.01.2017 EET • 24 часа и 1 секунда 01.01.2017-02.01.2017 EET Война данных: @alkovictor 88
  • 89. Дата DST и Магия Високосные секунды Было: 31.12.2016 23:59:60 (UTC) Пока нет точного графика Виновата Земля, Луна, Солнце и т.д. Разработчики тоже виноваты Война данных: @alkovictor 89
  • 90. Дата Зоны Временные зоны • позволяют работать с локальным временем Правила конвертации • позволяют преобразовывать в Instant • позволяют преобразовывать в другие зоны Война данных: @alkovictor 90
  • 91. Дата Зоны Запись Война данных: @alkovictor 91 PreparedStatement.setTimestamp( 1, new Timestamp(...), Calendar.getInstance( TimeZone.getTimeZone("UTC") ) );
  • 92. Дата Зоны Чтение Война данных: @alkovictor 92 Timestamp ts = ResultSet.getTimestamp( 1, Calendar.getInstance( TimeZone.getTimeZone("...") ) );
  • 93. Дата Зоны ЧЗХ #3 Война данных: @alkovictor 93 • UTC =? • Киев =? • Брюссель =? • *BD* =? Сохранили 2017-03-26 12:00+00:00
  • 94. Дата Зоны ЧЗХ #3 Война данных: @alkovictor 94 • UTC = 2017-03-26 15:00+03:00 [ 0] • Киев = 2017-03-26 12:00+03:00 [-3] • Брюссель = 2017-03-26 13:00+03:00 [-2] • *BD* = 2017-03-26 12:00:00.0 Сохранили 2017-03-26 12:00+00:00
  • 95. Дата Зоны ЧЗХ #3 Война данных: @alkovictor 95 Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp object in the Java programming language. This method uses the given calendar to construct an appropriate millisecond value for the timestamp if the underlying database does not store timezone information. • columnIndex - the first column is 1, the second is 2, ... • cal - the java.util.Calendar object to use in constructing the timestamp
  • 96. Дата Зоны А если надо? TIMESTAMP TIMESTAMP WITH TIME ZONE DATETIMEOFFSET Война данных: @alkovictor 96
  • 97. Дата Зоны ЧЗХ #4 Война данных: @alkovictor 97 • MS SQL v4 =? • Oracle v10 =? • Oracle v12 =? Сохранили 2017-03-26 12:00+00:00
  • 98. Дата Зоны ЧЗХ #4 Война данных: @alkovictor 98 • MS SQL v4 = 2017-03-26 12:00+00:00 • Oracle v10 = 2017-03-26 12:00+00:00 • Oracle v12 = 2017-03-26 12:00+03:00 Сохранили 2017-03-26 12:00+00:00
  • 99. Дата Зоны oracle.sql.TIMESTAMP Война данных: @alkovictor 99 public static byte[] toBytes(Timestamp var0, Calendar var1) { if (var0 == null) { return null; } int var2 = var0.getNanos(); byte[] var3 = var2 == 0 ? new byte[7] : new byte[11]; Calendar var4 = var1 == null ? Calendar.getInstance() : Calendar.getInstance(var1.getTimeZone()); var4.setTime(var0); int var5 = getOracleYear(var4); var3[0] = (byte) (var5 / 100 + 100); var3[1] = (byte) (var5 % 100 + 100); var3[2] = (byte) (var4.get(2) + 1); // Calendar.MONTH var3[3] = (byte) var4.get(5); // Calendar.DATE (DAY_OF_MONTH) var3[4] = (byte) (var4.get(11) + 1); // Calendar.HOUR_OF_DAY var3[5] = (byte) (var4.get(12) + 1); // Calendar.MINUTE var3[6] = (byte) (var4.get(13) + 1); // Calendar.SECOND if (var2 != 0) { var3[7] = (byte) (var2 >> 24); var3[8] = (byte) (var2 >> 16 & 255); var3[9] = (byte) (var2 >> 8 & 255); var3[10] = (byte) (var2 & 255); } return var3; }
  • 100. Дата Зоны ЧЗХ #4 Война данных: @alkovictor 100 • MS SQL v4 = 2017-03-26 12:00+00:00 • Oracle v10 = 2017-03-26 12:00+00:00 • Oracle v12 = 2017-03-26 12:00+00:00 Сохранили 2017-03-26 12:00+00:00
  • 101. Дата Зоны Что делать? Война данных: @alkovictor 101 Использовать только UTC Использовать “странный” API • void setObject(int, Object, int, int) Использовать java.time API или Calendar • ZonedDateTime and etc Не верить имплементаторам JDBC
  • 102. Дата Зоны Вопросы JavaScript клиент с непонятной зоной Java сервер с +03:00 зоной Как передавать даты? Война данных: @alkovictor 102
  • 103. Дата Зоны Ответы Дата не определена в спецификации JSON Long – это плохая идея для JavaScript String как ISO 8601 меньшее зло Война данных: @alkovictor 103
  • 104. Дата Зоны Итог Используй единую временную зону Тестируй драйвер на ожидаемое поведение • Например: https://github.com/victor-cr/jdbc-test *Не используй setTimestamp(…) для Instant Публикуй дату как строку в JSON API Война данных: @alkovictor 104
  • 105. Дата Итог Используй UTC как можно чаще Помни про разницу даты и Instant Работай с датами по закону Мерфи 24*60*60*1000 – это небезопасное упрощение Используй специальные библиотеки для работы с датами Война данных: @alkovictor 105

Notas del editor

  1. тема
  2. Чудесная Загадка Хорошая
  3. Быстрее
  4. Квинтиллион - это 10 в 18 степени
  5. Почистить
  6. Может базу сюда включить
  7. Надо больше информации