В типичном веб-приложении даты извлекаются из слоя базы данных, строго типизированного (например, в c # как System.DateTime в противоположность System.String).
Когда дату необходимо выразить в виде строки (например, отображаемой на странице), преобразование из DateTime в строку выполняется на уровне представления.
Почему это? Почему плохо конвертировать DateTime в строку на уровне базы данных?
Смотрите также горячие дебаты в чате и оригинальный вопрос, с которого все началось .
database
sql
formatting
Джон Ву
источник
источник
Ответы:
Даты, DateTimes и действительно любой другой типизированный объект, как правило, следует оставлять в их правильно типизированном формате до того момента, пока они не понадобятся для преобразования в какой-либо другой тип, особенно когда этот тип является удобочитаемой для человека формой, особенно когда это с потерями / односторонний вид конверсии.
Зачем? Поскольку предполагается, что тип предоставляет вам множество удобных встроенных функций, таких как правильное тестирование на равенство, сложение и вычитание, сравнение (больше чем, меньше чем), функциональность часового пояса и локали (особенно важно для всего, что связано со временем), и т.д. Если вы решили, что хотите поддержать американцев и формат «День месяца [й], год», а также общий британский стиль «День месяц год» или стандарт ISO «Год-месяц-день»? Что бы вы сделали, если бы это была строка, и вам нужно было внести это изменение, разобрать его обратно в Date? Тьфу, нет, спасибо - там много зла и подлых ошибок, которые лучше всего избегать.
В частности, вы упомянули многоуровневую архитектуру, в которой уровень представления данных отделен от данных позже. На самом деле это еще одна серьезная причина для передачи даты как даты, а не строки - потому что в какой тип форматирования строки следует указывать дату? Английский, китайский, с или без секунд / миллисекунд, полное название месяца или цифры, вы хотите отсортировать поле даты позже (сортировка по строке требует определенного формата строки, если вы хотите, чтобы она работала правильно) и т. Д.? Все это вопрос представления - как пользователь должен просматривать данные - и размещение этой логики в другом месте ограничит преимущество наличия многоуровневой архитектуры. База данных не должна знать или заботиться о том, как вы хотите просматривать дату в будущем.
Наконец, почти все сложные приложения (для которых нужны многоуровневые архитектуры), которые заботятся о времени, неизбежно будут использовать время / даты многими, многими различными способами и часто на всех различных уровнях архитектуры. Типизированные объекты, связанные со временем и датой, существуют по очень веской причине: само время, особенно системы календаря человека, странные и сложные. В конечном счете, времена и даты не являются строками по той же причине, что целые числа и числа с плавающей запятой не являются строками, и это только усложнит вашу жизнь, если вы попытаетесь притвориться, что они на самом деле являются просто массивами символов, потому что они просто не являются.
источник
Why? Because it is assumed that the type provides you with lots of handy built in functionality
На мой взгляд, это просто вторично. Настоящая причина в том, что тип говорит вам, что что-то есть . Дата не является строкой, она просто легко переводится в удобочитаемую строку.Я хочу знать тип.
Мне действительно все равно, хранит ли ваша база данных информацию в виде строки, нескольких целых или байтов, потому что, в конце концов, это всегда байты. Эта строка занимает больше места, чем нужно в вашей базе данных, меня не беспокоит. То, что беспокоит меня, сталкивается с датами как это:
11/10/2016
И не зная, одиннадцатый или десятый месяц.
Но это подтверждается, вы говорите. Конечно, вы прошли через процессы проверки. Дата совершенно правильная. Но здесь я поддерживаю эту вещь, и все, что я знаю, это дата - это строка. Я даже не могу сказать вам, что это за дата.
«Десятый день ноября в две тысячи шестнадцатый год нашего господина».
Это строка. Одна из наших презентаций нуждается в этом в этом формате. Вы сказали, что база данных конвертирует все даты в строки, верно? Веселитесь с этим.
Задача базы данных - хранить данные, а не представлять данные. Конечно, вы можете делать это в строках, но тогда вам нужно разобрать его, чтобы сделать его полезным для представления в других форматах. Хранение в стандартной разобранной форме для любого типа, который предлагает БД, позволяет нам быть как можно ближе к готовности представить без принятия решения о представлении. Для меня действительно не имеет значения, поддерживает ли БД этот тип строкой, целыми числами или байтами. Пока он знает, что делает.
Но когда вы не даете БД знать, что мы имеем дело с датой, и сохраняете дату в виде строки, вы преждевременно представляете ее и предпочитаете одну презентацию всем остальным. Это заставляет всех других докладчиков анализировать перед конвертацией. Нет, база данных не является частью уровня представления. Не проси об этом.
Аналогично, уровень представления не является частью базы данных, поэтому не стоит связывать отчет с деталями базы данных. Гораздо надежнее действовать на типы.
источник
место действия
Преобразование даты в строку для целей представления требует знания пользовательских предпочтений, поскольку одна и та же дата обычно должна отображаться по-разному для пользователей в разных локалях. Даже если вы используете одну локаль в вашем приложении, правильное поведение должно использовать локаль приложения вместо сервера базы данных; и они не гарантируются идентичными, даже если в этот момент они совпадают по совпадению.
Преобразование из универсального типа данных даты в строку, зависящую от локали, должно происходить на уровне представления, поскольку именно этот уровень знает, как должно выполняться это преобразование.
источник
Это нежелательно по той же причине, по которой вы не захотите просто слепо преобразовывать любой тип в строку, как только она достигнет уровня приложения. Существует высокая вероятность того, что вы захотите каким-то образом использовать этот объект, прежде чем представлять его пользователю (если вы даже представляете его пользователю). Для этого конкретного примера представьте, что вам нужно сделать некоторую математическую дату на объекте. Нет недостатка в том, чтобы просто преобразовать объект в строку перед тем, как вы ее отобразите.
источник
Типы существуют по определенной причине: если бы они не добавляли никакой выгоды, мы бы их не имели и не использовали бы, а у нас был бы просто «тип», и все было бы так. Они не только удобны, они также добавляют безопасность и эффективность. Ниже приведен список причин, по которым вы всегда должны сохранять типы в их собственном формате, а не в виде строк .
DateTime
Большую часть времени я использовал в качестве примера, но те же принципы применимы к любому примитивному типу, такому как целые, десятичные, двоичные и т. Д.Хранилище данных
Ограничения
Тип Ограничение
Почти все хранилища данных позволяют указывать ограничения на данные, в том числе ограничения типов. Одним из основных преимуществ указания
DateTime
экземпляра является то, что хранимые данные будут ограничены этим типом. Никогда нельзя будет вводить что-либо, кроме даты и времени, независимо от того, как данные были вставлены в хранилище. Последнее важно для больших систем, где есть несколько процессов, которые напрямую взаимодействуют с магазином. Сюда также входит попытка добавить ошибочные даты, например, 30 февраля (любого года), поскольку в феврале может быть только 29 дней в високосном году и 28 дней в течение не високосных.Ограничения валидации
Существуют также ограничения проверки, которые могут быть реализованы в хранилище данных, например, обеспечение того, чтобы вставленная дата не превышала текущую дату или чтобы дата начала наступала раньше даты окончания.
операции
Большинство хранилищ данных также имеют встроенные операции / функции, такие как
DateAdd
илиDatePart
в MS Sql Server. Это позволяет начать фильтрацию или выбор определенных данных, пока они еще находятся в хранилище (еще не загружены в приложение).Универсально принятый формат
При использовании нативного типа другие разработчики или системы, которые также взаимодействуют с хранилищем, не должны быть проинформированы о мельчайших деталях того, как хранится этот примитивный тип. Это не тот случай, если этот тип был сохранен как строка, тогда вы должны убедиться, что все понимают формат этого
DateTime
представления строки. Эта система становится хрупкой при работе с данными, которые охватывают локали, регионы и культуры в источнике данных, физическое местоположение приложения и атрибуты конечного пользователя / системы, взаимодействующей с этими данными. Пример: формат даты в одной стране может быть ММ / дд / гггг (как в США), но в другой это может быть дд / мм / гггг, обнаружение такой разницы становится практически невозможным.скорость
Скорость поиска, скорость проверки, скорость операций и эффективность хранения также являются важными факторами. Пример скорости извлечения: хранилища данных позволяют использовать индексы для столбцов, и эти индексы, как правило, могут использоваться более эффективно, если тип хранится в его собственном формате.
заявка
Доступ к данным
Выполнение запросов к хранилищу упрощается при использовании системы собственных типов, поскольку разработчикам, опять же, не нужно угадывать формат хранения. Почти все поставщики приложений хранилища данных ( пример: ado.net ) предоставляют механизмы для создания правильных параметризованных запросов на основе переданных собственных типов. Вот пример добавления части Date в запрос ado.net для хранилища Sql Server. делать то же самое со строками было бы очень громоздким и хрупким / подверженным ошибкам.
операции
Собственные типы в коде также обеспечивают стандартные операции, такие как тип .net
System.Date
. Операции обычно имеют математическую природу, такие как добавление дат, поиск различий между датами и т. Д. Опять же, это невозможно сделать для строковых типов.Уровень представления
место действия
Когда примитивный тип окончательно преобразуется в строку на уровне представления ( правильное расположение в программном стеке, чтобы сделать это ), у программиста теперь есть различные опции, чтобы правильно отобразить его в соответствии с контекстом, в котором он представлен. Этот контекст обычно состоит из фактического значения данных и языкового стандарта пользователя.
Пример 1Экземпляр datetime может быть автоматически отформатирован в зависимости от локали пользователя.
Пример 2Десятичный экземпляр может представлять сумму (валюту), и языковой стандарт пользователя должен также отображать сумму в соответствии с их предпочтениями. Приложение C # может затем отобразить значение с помощью
Это может иметь решающее значение, так как разные культуры показывают цифры по-разному. В США период (.) И запятая (,) имеют точное обратное значение, как в Нидерландах.
Место расположения
Это очень характерно для
DateTime
случаев. Дата и время представляют происшествие в определенный момент времени, но обычно это должно быть передано / представлено пользователю в зависимости от его собственного часового пояса. Пример:DateTime
экземпляр2016-09-21T23:38:21.399Z
может отображаться как9/21/2016 5:21 PM
для пользователя в восточном часовом поясе в США. Есть много способов сделать это, но это становится практически невозможным, если экземпляр даты и времени хранится в памяти как строковый тип или в хранилище данных как строковый тип.Главное правило
Общие 2 правила для приложения следуют, когда дело доходит до преобразования любого примитивного типа в строковое представление, как они
источник
В этом нет ничего плохого (это делается все время в службах), если вы используете не двусмысленный формат для вашей даты. Под однозначным пониманием я подразумеваю не только четкую дату (например, ММ / ДД и ДД / ММ), но и временную зону, в которой она находится. Поэтому заранее, если вы собираетесь представлять свои даты в виде текста, используйте формат ISO , Я настоятельно предпочитаю строки времени по UTC.
Плюсы:
Минусы:
Если бы кто-то сказал, что хочет это сделать, я бы спросил "почему?" потому что в этом нет особого смысла. Если причина, по которой кто-то хочет вернуть дату в виде строки, заключается в том, что он просто отображает ее напрямую, это не является хорошей причиной для использования строк из базы данных.
источник