2009-02-18 1 views
1

У меня есть приложение VB6, которое работает со значениями даты и времени в SQL Server (которые, очевидно, хранят даты как mm/dd/yyyy).Работа с датами в формате dd/mm/yyyy

Мне нужно представить эти даты пользователю как dd/mm/yyyy, прочитать их как dd/mm/yyyy, а затем сохранить их обратно в базу данных как стандартный mm/dd/yyyy.

Это те фрагменты кода, которые у меня есть, которые вставляют + вставляют даты, однако я прочитал много противоречивых методов обработки конверсий, и мне было интересно, знает ли кто-нибудь здесь четкое решение для этой ситуации.

"SELECT * FROM List WHERE DateIn LIKE '%" & txtDateIn.Text & "%'" 

"UPDATE [Progress] SET [Date] = '" & txtDate.Text & "'" 

txtDate.Text = "" & RecordSet.Fields("Date").Value 

Любые мысли? Заранее спасибо.

** Обновление

На самом деле я только что заметил, у меня есть даты, хранящиеся в полях даты и времени в виде 16/08/2009 00:00:00 которое дд/мм/гггг. Поэтому, возможно, я неправильно понял проблему. Но при попытке обновить значение datetime, которое я получаю, «преобразование типа данных символа в тип данных datetime приводит к значению дат-времени вне диапазона».

Я предполагал, что это связано с тем, что форматы даты не совпадали (что вызвало проблему с превышением значения месяца за пределами диапазона), однако у меня уже есть значения даты в формате день/месяц/год в поле даты и времени. И дата, отправленная в базу данных, определенно равна dd/mm/yyyy.

**** Update 2 **

Хорошо, кажется, есть некоторая путаница, я вызвал. Я извиняюсь.

  • Я храню даты как даты-времени в базе данных SQL
  • Тексты управления TextBox в применении VB6
  • Я бегу SQL SELECT заявления читать даты из базы данных и поместить значение в a TextBox
  • Затем у меня есть командная кнопка «commit», которая затем выполняет оператор UPDATE SQL, чтобы поместить значение TextBox в поле datetime в базе данных SQL.
  • Это работает отлично, до 1 конкретного случая.

В этом случае у меня есть значение даты и времени (которое SQL Server 2005 отображает как 16/08/2009 00:00:00), которое считывается из базы данных и заполняется TextBox значением 16/08/2009 , Теперь, когда я пытаюсь запустить инструкцию UPDATE без изменения текста TextBox, я получаю сообщение об ошибке «Преобразование типа данных char в тип данных datetime приводит к значению дат-времени вне диапазона».

Это не происходит с другими записями, например, с датой 04/08/2009, поэтому единственная проблема, которую я вижу, возможно, с положением дня и месяца в значении, потому что, если БД ожидает месяц первым то, очевидно, 16/08/2009 будет вне диапазона. Однако значение в базе данных уже 16/08/2009 без каких-либо проблем.

+0

Вам нужно, чтобы столбец DateIn являлся типом данных даты/даты, иначе у вас нет проверки даты и нет возможности «сравнивать» даты в хронологическом порядке. После того, как вы сделали это, не будет смысла. Я боюсь – Kristen

+0

Я никогда не пойму, как кто-то может воспринимать формат mm/dd/yyyy как «нормальный» или «очевидный». Сначала он не является ни частью, ни наименее важной частью, он просто запутан. – Svante

+0

@Harleqin Я имел в виду как по умолчанию. Я могу подумать, почему дата 03/04/2009 отлично работает, но 16/08/2009 дает выход из Ошибка диапазона - это то, что БД ожидает месяц сначала, а не день. Также при поиске проблемы я видел много случаев, когда люди хотели изменить формат с mm/dd/yyyy –

ответ

0

Ну, после всего этого проблема была простой. У меня есть значение даты, заключенное в одиночные (') и двойные (") кавычки. Проблема возникла из-за значений даты, не требующих одиночных кавычек. Удаление их решило проблему.

Благодарим вас в любом случае за помощь

9

SQL Server не «явно» хранит даты как mm/dd/yyyy. Насколько мне известно, он не хранит их в текстовом формате.

Я не знаю, что такое поддержка VB6 для параметризованных запросов, но это то, что вы хотите: в основном вы хотите передать аргумент в запрос как как дату, а не как текст.В основном вы должны проанализировать ввод пользователя в дату (каким бы то ни было способом VB6), а затем передать его в параметризованном запросе.

EDIT: Я попытался выяснить, как VB6 обрабатывает параметризованные запросы и не имел большой удачи - надеюсь, любая хорошая книга на VB6 покроет ее. (Есть множество примеров для VB.NET, конечно ...) Есть Wrox post, который дает пример; этого может быть достаточно, чтобы заставить вас идти.

РЕДАКТИРОВАТЬ: В комментарии к этому ответу и редактированию этого вопроса укажите, что есть некоторые путаницы в отношении того, каковы ваши типы данных. Пожалуйста, не используйте поля на основе символов для хранения дат: из этого ничего хорошего не может. Используйте правильное поле date/datetime/whatever, а затем убедитесь, что вы используете параметризованные запросы для доступа к базе данных, чтобы драйвер мог делать все необходимые преобразования. Опираясь на текстовый формат - это плохая идея.

+0

Похоже, что он хранит даты в базе данных в столбце на основе символов (обратите внимание на использование LIKE) вместо as столбец datetime. Переход к коду datetime, сохранение UTC в БД и выполнение локализации на клиенте - это, вероятно, путь. – tvanfosson

+0

Извините, если мой комментарий путают вещи. В базе данных я сохраняю дату как поле даты. Когда я просматриваю дату («открытая таблица», например, в SQL Server 2005), datetime отображается как dd/mm/yyy hh: mm: ss (как в 16/03/2009 00: 00: 000) Извините за confusion –

5

Используйте ODBC Каноническую форму даты или метки времени в ваших запросах. Это позволяет избежать любых недоразумений из-за локализации при хранении дат. Формат временной метки: {ts 'yyyy-mm-dd hh: mm: ss [.fff]'} Формат даты: {d 'yyyy-mm-dd'} Вот функции, которые я использую для этого.

Теперь, что касается ввода и отображения в VB6. В идеале вы должны использовать элемент управления datetimepicker вместо текстового поля, так как это возвращает дату, и при использовании этой даты вы не понимаете, какую дату вы выбираете. Но если вы можете предположить, что это всегда DD/MM/YYYY (это большой, если), вы можете использовать Format (datevalue, «DD/MM/YYYY») для его отображения. Чтобы прочитать его в переменной даты, вы не можете просто использовать CDate. Вам нужно будет использовать синтаксический анализ и что-то вроде DateSerial для объединения: DateSerial (Right (strDate, 4), Mid (strDate, 4, 2), Mid (strDate, 1, 2)).

' ------------------------------------------------------------------------------ 
' DateLiteral 
' 
' Description : 
' given a vb date, it returns a string with the odbc canonical date format. 
' 
' History 
' 2008-02-04 - WSR : added to this project 
' 
Public Function DateLiteral(ByRef dtSource As Date) As String 

    DateLiteral = _ 
     "{d '" & LeftPadDigits(Year(dtSource), 4) & "-" & _ 
       LeftPadDigits(Month(dtSource), 2) & "-" & _ 
       LeftPadDigits(Day(dtSource), 2) & "'}" 

End Function 
' ------------------------------------------------------------------------------ 


' ------------------------------------------------------------------------------ 
' TimeStampLiteral 
' 
' Description : 
' given a vb date, it returns a string with the odbc canonical timestamp format. 
' 
' History 
' 2008-02-04 - WSR : added to this project 
' 
Public Function TimeStampLiteral(ByRef dtSource As Date) As String 

    TimeStampLiteral = _ 
     "{ts '" & LeftPadDigits(Year(dtSource), 4) & "-" & _ 
       LeftPadDigits(Month(dtSource), 2) & "-" & _ 
       LeftPadDigits(Day(dtSource), 2) & " " & _ 
       LeftPadDigits(Hour(dtSource), 2) & ":" & _ 
       LeftPadDigits(Minute(dtSource), 2) & ":" & _ 
       LeftPadDigits(Second(dtSource), 2) & "'}" 

End Function 
' ------------------------------------------------------------------------------ 


' ------------------------------------------------------------------------------ 
' LeftPadDigits 
' 
' Description : pads the given string to the left with zeroes if it is under 
' the given length so that it is at least as long as the given length. 
' 
' History 
' 2008-02-04 - WSR : added to this project 
' 
Public Function LeftPadDigits(ByVal strSource As String, ByVal lngLength As Long) As String 

    If Len(strSource) < lngLength Then 
     LeftPadDigits = String$(lngLength - Len(strSource), "0") & strSource 
    Else 
     LeftPadDigits = strSource 
    End If 

End Function 
' ------------------------------------------------------------------------------ 

Также следует отметить, что первым выбором является использование ADO и параметризованных запросов. В моем случае я обращаюсь к базе данных через стороннюю библиотеку и не могу использовать параметризованные запросы. Таким образом, обработка букв даты. Однако здесь приведен пример запросов с параметрами ADO. Код может отличаться в зависимости от типа используемого ADO-соединения: OLEDB, ODBC или SQLNative. Иногда это не просто? для маркера параметра. Этот пример - OLEDB.

Set cmdVerifyUser = New ADODB.Command 
cmdVerifyUser.CommandType = adCmdText 
cmdVerifyUser.CommandTimeout = 30 
cmdVerifyUser.CommandText = "SELECT username FROM users WHERE userid = ?" 
cmdVerifyUser.Parameters.Append cmdVerifyUser.CreateParameter("userid", adVarChar, adParamInput, Len(m_strUserName), m_strUserName) 
cmdVerifyUser.ActiveConnection = m_conDatabase 
Set rstResults = cmdVerifyUser.Execute() 

If Not rstResults.EOF Then 
+0

Если по какой-то причине вы не можете использовать эту форму и должны использовать даты строки текста, используйте «yyyymmdd» или «yyyymmdd hh: mm: ss.mmm». Обратите внимание, что в первой части нет дефиса (в отличие от ODBC Каноническая форма). Они недвусмысленны и будут работать на любом SQL Server независимо от его конфигурации. – Kristen

+0

+1 за лучший ответ, чем Джон Скит! – MarkJ