Гость
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Формат даты и правильное его преобразование / 24 сообщений из 24, страница 1 из 1
25.06.2014, 07:29
    #38679190
Настенька
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Всем доброго дня. У пользователя в системе формат даты стоит такой: ddd dd.mm.yyyy, соответственно, все даты во всех программах высвечиваются так: Пн 23.06.2014.
Есть vsflexgrid, там поле дата, и соответственно, там также дата высвечивается: Пн 23.06.2014.

Раньше, когда был обычный формат даты: dd.mm.yyyy, такая процедура срабатывала нормально (проверяет, если дата меньше текущей, то подсвечивает красным, т.е. она уже просрочена)

Код: vbnet
1.
If Format(VSFlexGrid1.Cell(flexcpText, Row, 5), "yyyy-mm-dd") < Format(Date, "yyyy-mm-dd") Then VSFlexGrid1.Cell(flexcpForeColor, Row, 5) = vbRed



Теперь это преобразование не подходит. Помогите, как правильно переписать этот код, исходя из любого формата даты (он необязательно может быть таким, как я выше привела из примера). Заранее всем спасибо.
...
Рейтинг: 0 / 0
25.06.2014, 08:22
    #38679207
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Настенькатакая процедура срабатывалатакая процедура сама по себе несколько дикая, зачем форматировать дату в текст и сверять между собой текстовые строки? Надо преобразовывать аргументы в тип Date и сверять между собой даты.

Соответственно, нужно парсить flexcpText в дату и сверять с текущей (без всякого форматирования). Соответственно, нужно написать парсер, который считывает и расшифровывает текущий системный формат даты и в соответствии с ним обрабатывает входящую строку. CDate тут бессилен.

А вообще - как данные вообще попадают в flexgrid? может лучше там поколдовать - красить данные заранее при заполнении грида или сделать признак в скрытом столбце или переформатировать дату в нужный формат....
...
Рейтинг: 0 / 0
25.06.2014, 08:23
    #38679208
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Настенька,

как то так.
На самом деле гарантий что это будет работать с теми РАЗНЫМИ и ОТ БАЛДЫ примерами констант что я написал нет (почему-то работает).
Но если на тек. клиентском компьютере он эти даты пишет (в формате своей системы), а потом на том же компе программа их читает,
то IsDate будет true и сравниваться будет все правильно.

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
Private Sub Command1_Click()
  Const strDate1 As String = "1992-03-21"
  Const strDate2 As String = "22-03-1993"
  Dim Date1 As Date, Date2 As Date
  
  If IsDate(strDate1) Then
    Date1 = CDate(strDate1)
  Else
    Exit Sub
  End If
  
  If IsDate(strDate2) Then
    Date2 = CDate(strDate2)
  Else
    Exit Sub
  End If
  
  MsgBox (Date2 > Date1)
  MsgBox DateDiff("d", Date1, Date2)
End Sub
...
Рейтинг: 0 / 0
25.06.2014, 08:30
    #38679210
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Дим, я проверил - такой формат "ddd dd.mm.yyyy" CDate понимать не хочет, даже если он прописан в системе.
...
Рейтинг: 0 / 0
25.06.2014, 08:32
    #38679214
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
А вот если клиент сохраняет форматированный текст у себя,
а потом это читается на другом компе (с другими региональными настройками), то это может и не прокатить, как Шокер намекнул.

Но я лично такими фишками пользуюсь.
Т.е. например дата хранимая в БД (как дата) на русском и американском компе будет в проге отображаться по разному.

Или например могу в реестр записать CStr(as Date) а потом точно также оттуда вытащить как CDate(As String). На ДАННОМ компе проблем никогда не будет, но IsDate все-таки лучше проверять (а вдруг юзер мазохист и форматы постоянно меняет).

Это можно долго рассуждать...
...
Рейтинг: 0 / 0
25.06.2014, 08:36
    #38679216
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Shocker.Pro,

надоело.
подскажи чего-нибудь сам.

Я тут счас более умное дело делаю - впихиваю системную иконку (типа SIID_HELP) в заголовок формы. Сделаю, расскажу в соседней теме.
...
Рейтинг: 0 / 0
25.06.2014, 08:44
    #38679221
Настенька
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Вот проверила сейчас этот код (поставила формат даты в системе ddd dd.mm.yyyy), выдает false, даты не сравнивает никак

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
Private Sub CommandButton1_Click()
  Dim strDate1 As Date
  Const strDate2 As String = "22-03-1993"
  Dim Date1 As Date, Date2 As Date
  strDate1 = Date
  If IsDate(strDate1) Then
    Date1 = CDate(strDate1)
  Else
    Exit Sub
  End If
  
  If IsDate(strDate2) Then
    Date2 = CDate(strDate2)
  Else
    Exit Sub
  End If
  
  MsgBox (Date2 > Date1)
  MsgBox DateDiff("d", Date1, Date2)

End Sub



Люди добрые, ну помогите. Проблема не решена.
...
Рейтинг: 0 / 0
25.06.2014, 09:15
    #38679243
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Ну знаете
Код: vbnet
1.
Date1 = CDate(CStr(Now))


Да, при вашем формате выдает ошибку. Значит функция тупая такая. Хотя я не думал что настолько.

Настенька,

парсер пиши. Причем под каждого клиента видимо свой.
Для указанного случая видимо достаточно убрать начало строки до первого пробела,
день недели никакой доп. информации все одно не несет.

Или храни даты как Date (неважно что там высвечивается). И сравнивай то что хранишь, а не то что высвечиваешь.

В принципе Шокер все правильно тебе сказал.
...
Рейтинг: 0 / 0
25.06.2014, 09:52
    #38679295
Настенька
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Дмитрий77, помогите пож-та правильно написать этот парсер. Например, я же не знаю точно, какой формат даты будет стоять у пользователя на компьютере. Варианты: Ср 01.01.2014, Ср01.01.2014 и т.д. (с пробелом, без пробела)

Как правильно его написать?
...
Рейтинг: 0 / 0
25.06.2014, 10:29
    #38679359
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Настенька,
>Варианты: Ср 01.01.2014,
Ну берешь например вот так
Код: vbnet
1.
CDate(Right(the_str, len(the_str)- instr(the_str," ")))

и сравниваешь


>Ср01.01.2014

Код: vbnet
1.
cdate(Right(the_str, len(the_str)- 2))



На любое извращение пишешь свое извращение.
...
Рейтинг: 0 / 0
25.06.2014, 10:31
    #38679362
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Мое сообщение 16214774 проигнорировано?

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

ЗЫ: Кстати, пользователь в вырожденном случае может поставить дату в формате dd-mm например (без года) и ваша программа вообще не будет работать правильно. Так что лучше все-таки не отдавать данные на откуп пользователю. Расскажите, как данные попадают в сетку.
...
Рейтинг: 0 / 0
25.06.2014, 10:36
    #38679370
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Пиши изначально свою программу так, чтоб она хранила данные либо в Date,
либо в любом но известном программе (и тебе) формате.

Из твоего формата дату всегда можно достать и отобразить в тек. системном.
Код: vbnet
1.
Function DateSerial(Year As Integer, Month As Integer, Day As Integer)



Но не надо путать отображение и то как оно хранится.
...
Рейтинг: 0 / 0
25.06.2014, 11:03
    #38679408
Настенька
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Спасибо всем за ответы, вы мне очень помогли, проблема решена. :-). Всем хорошего дня.
...
Рейтинг: 0 / 0
25.06.2014, 11:12
    #38679417
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Shocker.ProНастенькаНапример, я же не знаю точно, какой формат даты будет стоять у пользователя на компьютере.его нужно считывать системными функциями расшифровывать дату в соответствии с ним. Это не самая простая задача,
Если CDate настолько гнилая, то да, надо искать API и вытаскивать формат. А потом парсить в соответствии с ним. Здесь поддерживаю.
Но я в (видимо этих) API копался только однажды, когда сортировал API-шный ListView по дате. Поищите мои топики (Listview + API + сортировка по дате) если интересно.
...
Рейтинг: 0 / 0
25.06.2014, 11:24
    #38679439
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Дмитрий77Но я в (видимо этих) API копался только однажды, когда сортировал API-шный ListView по дате. Поищите мои топики (Listview + API + сортировка по дате) если интересно.

ГЫ. И кстати моя сортировка в указанном вами дебильном формате Пн 23.06.2014
подглючивает видимо по тем же причинам (хотя и не вылетает, видимо проверки делаю).
Я именно показываю в Current System Format и сравниваю именно хитро форматированные строки а не даты.
И кстати по причине оч. низкой скорости сравнения именно дат (в десятки раз).

И не буду я даже сейчас это у себя лечить. При стандартных нормальных форматах (хоть французских, хоть английских, хоть китайских) - когда выбираешь страну а не отсутствующую по дефолту в комбобоксе отсебятину сортирует правильно.
...
Рейтинг: 0 / 0
25.06.2014, 11:50
    #38679503
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Я все таки залез в свой код.
Что я делаю, так это достаю дату DateFromString(hMem) т.е. через VarDateFromStr
И VarDateFromStr не справляется.

Хотя я уже догадываюсь что собака зарыта в
Код: vbnet
1.
GetUserDefaultLCID()


Потому что GetUserDefaultLCID -это dd.MM.yyyy , а не ddd dd.MM.yyyy , т.е. не отсебятина, кот. юзер напридумал своими кривыми ручонками.
И отсюда коммент:
Код: vbnet
1.
2.
 ' Do not want user's own settings to override the standard formatting settings
  ' if they are using the same locale that we are converting from.



В случае API я думаю есть над чем поколдовать, чтобы это полечить.
А вот CDate очевидно умеет только GetUserDefaultLCID

GetUserDefaultLCID function

Caution If the user default locale is a custom locale, an application cannot accurately tag data with the value or exchange it. In this case, the application should use GetUserDefaultLocaleName in preference to GetUserDefaultLCID.

Ну, т.е направление понятно. Надо использовать VarDateFromStr и вместо GetUserDefaultLCID делать что-то другое, тогда будет работать. Но мне лично в это врубаться счас неохота.


Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
    iItemCount = SendMessage(hListView, LVM_GETITEMCOUNT, 0, 0)
    If iItemCount = 0 Then Exit Function
    Dim lvc As LV_COLUMN
    lvc.mask = LVCF_WIDTH
    lvc.cx = 0
    m_lColumn = SendMessage(hListView, LVM_INSERTCOLUMN, _
     SendMessageLong(SendMessageLong(hListView, LVM_GETHEADER, 0, 0), HDM_GETITEMCOUNT, 0, 0), lvc)
    Dim hMem As Long
    hMem = GlobalLock(GlobalAlloc(&H40, MAX_LVMSTRING))
    Dim lvi_receive As LVITEM
    lvi_receive.mask = LVIF_TEXT
    lvi_receive.cchTextMax = MAX_LVMSTRING
    lvi_receive.pszText = hMem
    lvi_receive.iSubItem = Column
    Dim lvi_send As LVITEM
    lvi_send.mask = LVIF_TEXT
    lvi_send.iSubItem = m_lColumn
    For i = 0 To iItemCount - 1
      Call SendMessage(hListView, LVM_GETITEMTEXTW, i, lvi_receive)
      lvi_send.iItem = i
      lvi_send.pszText = StrPtr(Format$(DateFromString(hMem), "yyyymmddhhmmss"))
      Call SendMessage(hListView, LVM_SETITEMW, 0, lvi_send)
    Next
    GlobalFree hMem
  Else
    m_lColumn = CLng(Column)
  End If




Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
Public Function DateFromString(ByVal sDateIn As Long) As Date
  Dim hResult As Long
  Dim dtOut As Date
  ' Do not want user's own settings to override the standard formatting settings
  ' if they are using the same locale that we are converting from.
  '
  Const LOCALE_NOUSEROVERRIDE = &H80000000

  ' Do the conversion
  hResult = VarDateFromStr(sDateIn, GetUserDefaultLCID(), LOCALE_NOUSEROVERRIDE, dtOut)

  ' Check return value to catch any errors.
  '
  ' Can change the code below to return standard VB6 error codes instead
  ' (i.e. DISP_E_TYPEMISMATCH = "Type Mismatch" = error code 13)
  '
  Select Case hResult
    Case S_OK:
      DateFromString = dtOut
'    Case DISP_E_BADVARTYPE:
'      Debug.Print "DISP_E_BADVARTYPE"
'    Case DISP_E_OVERFLOW:
'      Debug.Print "DISP_E_OVERFLOW"
'    Case DISP_E_TYPEMISMATCH:
'      Debug.Print "DISP_E_TYPEMISMATCH"
'    Case E_INVALIDARG:
'      Debug.Print "E_INVALIDARG"
'    Case E_OUTOFMEMORY:
'      Debug.Print "E_OUTOFMEMORY"
'    Case Else
'      Debug.Print hResult
  End Select
End Function
...
Рейтинг: 0 / 0
25.06.2014, 12:04
    #38679529
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
VarDateFromStr function
Возможно в моем API-случае причина еще в этом флаге, кот. у меня в коде:
авторLOCALE_NOUSEROVERRIDE Uses the system default locale settings, rather than custom locale settings.

Ну т.е. надо скормить в VarDateFromStr правильный формат
1) текущего пользователя
2) и не дефолтный, а именно с учетом того что юзер наковырял в язык и рег. стандарты в дополнение к дефолтному

Собственно "собака зарыта на этом участке площадью 1 кв.км".
...
Рейтинг: 0 / 0
26.06.2014, 10:37
    #38680591
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Дмитрий77 VarDateFromStr function
Возможно в моем API-случае причина еще в этом флаге, кот. у меня в коде:

Ну т.е. надо скормить в VarDateFromStr правильный формат
...
2) и не дефолтный, а именно с учетом того что юзер наковырял в язык и рег. стандарты в дополнение к дефолтному

А вот и не получается ничего.

CStr(as Date) (частный случай Now() as String ) всегда форматирует согласно кастомизированному формату Short Date (по умолчанию он совпадает с одним из дефолтных, но в случае "ddd dd.mm.yyyy" - не совпадает)

Что до CDate (as String), то это граффер над VarDateFromStr

Код: plaintext
1.
2.
3.
4.
5.
6.
HRESULT VarDateFromStr(
  _In_   LPCOLESTR strIn,
  _In_   LCID lcid,
  _In_   ULONG dwFlags,
  _Out_  DATE *pdateOut
);



Играться можно только выделенными параметрами.
LCID - это locale identifier -целое число
Чтоб понятней: 1049 -русский 1033 -английский
Причем каких-то LCID-ов отличных от зарезервированных (которые учитывают нестандартные настройки типа "ddd dd.mm.yyyy" и которые бы можно было вычислить) как я понял не существует.
Что до dwFlags -единственный интересный флаг это LOCALE_NOUSEROVERRIDE , но его отсутствие/присутствие ничего не дает, проверял. Скорее всего, имеется ввиду язык системы(дефолтный)/язык юзера

Т.е. не удается заставить VarDateFromStr понимать "ddd dd.mm.yyyy" , она смотрит на LCID, а LCID информации о нестандартных Short Date не предоставляет.
Это объясняет почему CDate ( "ddd dd.mm.yyyy" as String) также не работает.

Все, больше параметров нет.

Shocker.Pro, который считывает и расшифровывает текущий системный формат даты....
Что имел ввиду?
Как прочитать текущий системный формат даты?

Есть ф-ции типа EnumDateFormats function , но у них аргумен все тот же LCID Locale, то бишь 1049,1033
Понятно что custom format они не вернут.

Потому что вопрос конечно интересный. И сортировка ListView у меня для случая "ddd dd.mm.yyyy" не работает, по тем же причинам, по которым возникли проблемы у автора топика. Т.е. меня это в итоге зацепило.

Какие еще идеи кроме "парсить ручками в каждом конкретном случае"?
...
Рейтинг: 0 / 0
26.06.2014, 10:44
    #38680600
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
я не знаю, предполагал, что надо гуглить, с уверенностью, что прочитать его можно.

есть смешной способ - попросить систему отформатировать заранее известную дату типа 22-11-3333 и посмотреть, что куда попало ))
...
Рейтинг: 0 / 0
26.06.2014, 11:23
    #38680640
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Shocker.Proя не знаю, предполагал, что надо гуглить, с уверенностью, что прочитать его можно.
Его надо не просто просчитать, его надо подставить в ф-цию VarDateFromStr (или какую другую ???).
И я вроде как пришел к выводу, что не получается.

Shocker.Proесть смешной способ - попросить систему отформатировать заранее известную дату типа 22-11-3333 и посмотреть, что куда попало ))
Не,ну DateSerial()
А дальше? Ковырять и парсить ручками?
Плохой вариант. Если система позволяет задавать нестандартные форматы, значит она должна уметь их парсить назад в Date. Должен быть способ.

Хотя твой пример с
dd-mm например (без года)
заставляет задуматься насчет "должна".
А с другой стороны, почему нет, должна подставить дефолтный год тогда.
Код: vbnet
1.
2.
3.
4.
print cdate("22-05")
22.05.2014 
print cdate("22")
21.01.1900 


GetDateFormat function -но она похоже именно форматирует в заданном формате, а не дает тек. формат.
...
Рейтинг: 0 / 0
26.06.2014, 12:45
    #38680718
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Получить форматированную дату as String (без VB-шного Format) несложно.
Я намеренно упростил и использую lpDate=NULL //=Now()

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Public Declare Function GetDateFormat Lib "kernel32.dll" Alias "GetDateFormatA" ( _
 ByVal Locale As Long, ByVal dwFlags As Long, ByRef lpDate As Any, _
 ByVal lpFormat As String, ByVal lpDateStr As String, ByVal cchDate As Long) As Long

Public Function DateNowFormatted(ByVal Locale As Long, ByVal lpFormat As String) As String
  Dim cch As Long
  Dim strBuf As String
  cch = GetDateFormat(Locale, 0, ByVal 0&, lpFormat, strBuf, 0)
  strBuf = String(cch, 0)
  cch = GetDateFormat(Locale, 0, ByVal 0&, lpFormat, strBuf, cch)
  DateNowFormatted = Left(strBuf, InStr(strBuf, Chr(0)) - 1)
End Function

Результат:
Код: vbnet
1.
2.
3.
4.
print DateNowFormatted(1049, "ddd dd.MM.yyyy")
Чт 26.06.2014
print DateNowFormatted(1033, "ddd dd.MM.yyyy")
Thu 26.06.2014



Очевидно, что CStr (as Date) делает следующее:
1) Вычисляет тек. LCID (=1049)
2) Вынимает из настроек OS "ddd dd.MM.yyyy" (Short Date Format)
3) Запускает код типа того что я накатал

Т.е. по сути нужно следующее:
1) Вычислить тек. LCID (это не проблема - GetUserDefaultLCID function или ей подобные)
2) Вычислить из настроек OS "ddd dd.MM.yyyy" (тупо формат как там забит) Вопрос как?
3) обратный парсер dd->Число as Long, MM -месяц as Long Вопрос что за ф-ция?

Очевидно, что упомянутая VarDateFromStr==CDate(As String) берет на вход только LCID,
а вместо пункта (2) подставляет дефолты на основе LCID,
но при этом в системе существует ф-ция "обратный парсер" ибо очевидно что VarDateFromStr ей пользуется.
Для начала надо понять что это за ф-ция.
...
Рейтинг: 0 / 0
26.06.2014, 12:52
    #38680726
Konst_One
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
http://vbnet.mvps.org/code/locale/localedates.htm



module.bas:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
 Public Const LOCALE_ILANGUAGE             As Long = &H1     'language id
Public Const LOCALE_SLANGUAGE             As Long = &H2     'localized name of language
Public Const LOCALE_SENGLANGUAGE          As Long = &H1001  'English name of language
Public Const LOCALE_SABBREVLANGNAME       As Long = &H3     'abbreviated language name
Public Const LOCALE_SNATIVELANGNAME       As Long = &H4     'native name of language

Public Const LOCALE_ICOUNTRY              As Long = &H5     'country code
Public Const LOCALE_SCOUNTRY              As Long = &H6     'localized name of country
Public Const LOCALE_SENGCOUNTRY           As Long = &H1002  'English name of country
Public Const LOCALE_SABBREVCTRYNAME       As Long = &H7     'abbreviated country name
Public Const LOCALE_SNATIVECTRYNAME       As Long = &H8     'native name of country

Public Const LOCALE_IDEFAULTLANGUAGE      As Long = &H9     'default language id
Public Const LOCALE_IDEFAULTCOUNTRY       As Long = &HA     'default country code
Public Const LOCALE_IDEFAULTCODEPAGE      As Long = &HB     'default oem code page
Public Const LOCALE_IDEFAULTANSICODEPAGE  As Long = &H1004  'default ansi code page
Public Const LOCALE_IDEFAULTMACCODEPAGE   As Long = &H1011  'default mac code page

Public Const LOCALE_SLIST                 As Long = &HC     'list item separator
Public Const LOCALE_IMEASURE              As Long = &HD     '0 = metric, 1 = US

Public Const LOCALE_SDECIMAL              As Long = &HE     'decimal separator
Public Const LOCALE_STHOUSAND             As Long = &HF     'thousand separator
Public Const LOCALE_SGROUPING             As Long = &H10    'digit grouping
Public Const LOCALE_IDIGITS               As Long = &H11    'number of fractional digits
Public Const LOCALE_ILZERO                As Long = &H12    'leading zeros for decimal
Public Const LOCALE_INEGNUMBER            As Long = &H1010  'negative number mode
Public Const LOCALE_SNATIVEDIGITS         As Long = &H13    'native ascii 0-9

Public Const LOCALE_SCURRENCY             As Long = &H14    'local monetary symbol
Public Const LOCALE_SINTLSYMBOL           As Long = &H15    'intl monetary symbol
Public Const LOCALE_SMONDECIMALSEP        As Long = &H16    'monetary decimal separator
Public Const LOCALE_SMONTHOUSANDSEP       As Long = &H17    'monetary thousand separator
Public Const LOCALE_SMONGROUPING          As Long = &H18    'monetary grouping
Public Const LOCALE_ICURRDIGITS           As Long = &H19    '# local monetary digits
Public Const LOCALE_IINTLCURRDIGITS       As Long = &H1A    '# intl monetary digits
Public Const LOCALE_ICURRENCY             As Long = &H1B    'positive currency mode
Public Const LOCALE_INEGCURR              As Long = &H1C    'negative currency mode

Public Const LOCALE_SDATE                 As Long = &H1D    'date separator
Public Const LOCALE_STIME                 As Long = &H1E    'time separator
Public Const LOCALE_SSHORTDATE            As Long = &H1F    'short date format string
Public Const LOCALE_SLONGDATE             As Long = &H20    'long date format string
Public Const LOCALE_STIMEFORMAT           As Long = &H1003  'time format string
Public Const LOCALE_IDATE                 As Long = &H21    'short date format ordering
Public Const LOCALE_ILDATE                As Long = &H22    'long date format ordering
Public Const LOCALE_ITIME                 As Long = &H23    'time format specifier
Public Const LOCALE_ITIMEMARKPOSN         As Long = &H1005  'time marker position
Public Const LOCALE_ICENTURY              As Long = &H24    'century format specifier (short date)
Public Const LOCALE_ITLZERO               As Long = &H25    'leading zeros in time field
Public Const LOCALE_IDAYLZERO             As Long = &H26    'leading zeros in day field (short date)
Public Const LOCALE_IMONLZERO             As Long = &H27    'leading zeros in month field (short date)
Public Const LOCALE_S1159                 As Long = &H28    'AM designator
Public Const LOCALE_S2359                 As Long = &H29    'PM designator

Public Const LOCALE_ICALENDARTYPE         As Long = &H1009  'type of calendar specifier
Public Const LOCALE_IOPTIONALCALENDAR     As Long = &H100B  'additional calendar types specifier
Public Const LOCALE_IFIRSTDAYOFWEEK       As Long = &H100C  'first day of week specifier
Public Const LOCALE_IFIRSTWEEKOFYEAR      As Long = &H100D  'first week of year specifier

Public Const LOCALE_SDAYNAME1             As Long = &H2A    'long name for Monday
Public Const LOCALE_SDAYNAME2             As Long = &H2B    'long name for Tuesday
Public Const LOCALE_SDAYNAME3             As Long = &H2C    'long name for Wednesday
Public Const LOCALE_SDAYNAME4             As Long = &H2D    'long name for Thursday
Public Const LOCALE_SDAYNAME5             As Long = &H2E    'long name for Friday
Public Const LOCALE_SDAYNAME6             As Long = &H2F    'long name for Saturday
Public Const LOCALE_SDAYNAME7             As Long = &H30    'long name for Sunday
Public Const LOCALE_SABBREVDAYNAME1       As Long = &H31    'abbreviated name for Monday
Public Const LOCALE_SABBREVDAYNAME2       As Long = &H32    'abbreviated name for Tuesday
Public Const LOCALE_SABBREVDAYNAME3       As Long = &H33    'abbreviated name for Wednesday
Public Const LOCALE_SABBREVDAYNAME4       As Long = &H34    'abbreviated name for Thursday
Public Const LOCALE_SABBREVDAYNAME5       As Long = &H35    'abbreviated name for Friday
Public Const LOCALE_SABBREVDAYNAME6       As Long = &H36    'abbreviated name for Saturday
Public Const LOCALE_SABBREVDAYNAME7       As Long = &H37    'abbreviated name for Sunday
Public Const LOCALE_SMONTHNAME1           As Long = &H38    'long name for January
Public Const LOCALE_SMONTHNAME2           As Long = &H39    'long name for February
Public Const LOCALE_SMONTHNAME3           As Long = &H3A    'long name for March
Public Const LOCALE_SMONTHNAME4           As Long = &H3B    'long name for April
Public Const LOCALE_SMONTHNAME5           As Long = &H3C    'long name for May
Public Const LOCALE_SMONTHNAME6           As Long = &H3D    'long name for June
Public Const LOCALE_SMONTHNAME7           As Long = &H3E    'long name for July
Public Const LOCALE_SMONTHNAME8           As Long = &H3F    'long name for August
Public Const LOCALE_SMONTHNAME9           As Long = &H40    'long name for September
Public Const LOCALE_SMONTHNAME10          As Long = &H41    'long name for October
Public Const LOCALE_SMONTHNAME11          As Long = &H42    'long name for November
Public Const LOCALE_SMONTHNAME12          As Long = &H43    'long name for December
Public Const LOCALE_SMONTHNAME13          As Long = &H100E  'long name for 13th month (if exists)
Public Const LOCALE_SABBREVMONTHNAME1     As Long = &H44    'abbreviated name for January
Public Const LOCALE_SABBREVMONTHNAME2     As Long = &H45    'abbreviated name for February
Public Const LOCALE_SABBREVMONTHNAME3     As Long = &H46    'abbreviated name for March
Public Const LOCALE_SABBREVMONTHNAME4     As Long = &H47    'abbreviated name for April
Public Const LOCALE_SABBREVMONTHNAME5     As Long = &H48    'abbreviated name for May
Public Const LOCALE_SABBREVMONTHNAME6     As Long = &H49    'abbreviated name for June
Public Const LOCALE_SABBREVMONTHNAME7     As Long = &H4A    'abbreviated name for July
Public Const LOCALE_SABBREVMONTHNAME8     As Long = &H4B    'abbreviated name for August
Public Const LOCALE_SABBREVMONTHNAME9     As Long = &H4C    'abbreviated name for September
Public Const LOCALE_SABBREVMONTHNAME10    As Long = &H4D    'abbreviated name for October
Public Const LOCALE_SABBREVMONTHNAME11    As Long = &H4E    'abbreviated name for November
Public Const LOCALE_SABBREVMONTHNAME12    As Long = &H4F    'abbreviated name for December
Public Const LOCALE_SABBREVMONTHNAME13    As Long = &H100F  'abbreviated name for 13th month (if exists)

Public Const LOCALE_SPOSITIVESIGN         As Long = &H50    'positive sign
Public Const LOCALE_SNEGATIVESIGN         As Long = &H51    'negative sign
Public Const LOCALE_IPOSSIGNPOSN          As Long = &H52    'positive sign position
Public Const LOCALE_INEGSIGNPOSN          As Long = &H53    'negative sign position
Public Const LOCALE_IPOSSYMPRECEDES       As Long = &H54    'mon sym precedes pos amt
Public Const LOCALE_IPOSSEPBYSPACE        As Long = &H55    'mon sym sep by space from pos amt
Public Const LOCALE_INEGSYMPRECEDES       As Long = &H56    'mon sym precedes neg amt
Public Const LOCALE_INEGSEPBYSPACE        As Long = &H57    'mon sym sep by space from neg amt

'#if(WINVER >= &H0400)
Public Const LOCALE_FONTSIGNATURE         As Long = &H58    'font signature
Public Const LOCALE_SISO639LANGNAME       As Long = &H59    'ISO abbreviated language name
Public Const LOCALE_SISO3166CTRYNAME      As Long = &H5A    'ISO abbreviated country name
'#endif /* WINVER >= &H0400 */

'#if(WINVER >= &H0500)
Public Const LOCALE_IDEFAULTEBCDICCODEPAGE As Long = &H1012 'default ebcdic code page
Public Const LOCALE_IPAPERSIZE            As Long = &H100A  '0 = letter, 1 = a4, 2 = legal, 3 = a3
Public Const LOCALE_SENGCURRNAME          As Long = &H1007  'english name of currency
Public Const LOCALE_SNATIVECURRNAME       As Long = &H1008  'native name of currency
Public Const LOCALE_SYEARMONTH            As Long = &H1006  'year month format string
Public Const LOCALE_SSORTNAME             As Long = &H1013  'sort name
Public Const LOCALE_IDIGITSUBSTITUTION    As Long = &H1014  '0 = none, 1 = context, 2 = native digit
'#endif /* WINVER >=  &H0500 */

Public Declare Function GetThreadLocale Lib "kernel32" () As Long

Public Declare Function GetSystemDefaultLCID Lib "kernel32" () As Long

Public Declare Function GetLocaleInfo Lib "kernel32" _
   Alias "GetLocaleInfoA" _
  (ByVal Locale As Long, _
   ByVal LCType As Long, _
   ByVal lpLCData As String, _
   ByVal cchData As Long) As Long


Public Function GetUserLocaleInfo(ByVal dwLocaleID As Long, ByVal dwLCType As Long) As String

   Dim sReturn As String
   Dim r As Long

  'call the function passing the Locale type
  'variable to retrieve the required size of
  'the string buffer needed
   r = GetLocaleInfo(dwLocaleID, dwLCType, sReturn, Len(sReturn))
    
  'if successful..
   If r Then
    
     'pad the buffer with spaces
      sReturn = Space$(r)
       
     'and call again passing the buffer
      r = GetLocaleInfo(dwLocaleID, dwLCType, sReturn, Len(sReturn))
     
     'if successful (r > 0)
      If r Then
      
        'r holds the size of the string
        'including the terminating null
         GetUserLocaleInfo = Left$(sReturn, r - 1)
      
      End If
   
   End If
    
End Function



form1.frm
Create a form containing 13 textboxes named Text0 through Text12 (not in a control array). Add labels as desired, and a command button (Command1).

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
Option Explicit


Private Sub Command1_Click()

   Dim LCID As Long
   
   LCID = GetSystemDefaultLCID()
  
  'language id
   Text0.Text = GetUserLocaleInfo(LCID, LOCALE_ILANGUAGE)
  
  'localized name of language
   Text1.Text = GetUserLocaleInfo(LCID, LOCALE_SLANGUAGE)
  
  'English name of language
   Text2.Text = GetUserLocaleInfo(LCID, LOCALE_SENGLANGUAGE)
  
  'Long date format-ordering specifier
   Select Case GetUserLocaleInfo(LCID, LOCALE_ILDATE)
      Case "0": Text3.Text = "0   Month - Day - Year"
      Case "1": Text3.Text = "1   Day - Month - Year"
      Case "2": Text3.Text = "2   Year - Month - Day"
   End Select
   
  'Long date format string
   Text4.Text = GetUserLocaleInfo(LCID, LOCALE_SLONGDATE)
   
  'Long date format-ordering specifier
   Select Case GetUserLocaleInfo(LCID, LOCALE_IDATE)
      Case "0": Text5.Text = "0   Month - Day - Year"
      Case "1": Text5.Text = "1   Day - Month - Year"
      Case "2": Text5.Text = "2   Year - Month - Day"
   End Select
     
  'Short date format string
   Text6.Text = GetUserLocaleInfo(LCID, LOCALE_SSHORTDATE)
   
  'century format specifier - placement in
  'the string of the year component (short date)
   Text7.Text = GetUserLocaleInfo(LCID, LOCALE_ICENTURY)
   
  'Date separator chr
   Text8.Text = GetUserLocaleInfo(LCID, LOCALE_SDATE)
   
  'Current calendar type
   Select Case GetUserLocaleInfo(LCID, LOCALE_ICALENDARTYPE)
      Case "1":  Text9.Text = "1 Gregorian (localized) "
      Case "2":  Text9.Text = "2 Gregorian (English strings always)"
      Case "3":  Text9.Text = "3 Era: Year of the Emperor (Japan)"
      Case "4":  Text9.Text = "4 Era: Year of Taiwan Region"
      Case "5":  Text9.Text = "5 Tangun Era(Korea)"
      Case "6":  Text9.Text = "6 Hijri (Arabic lunar)"
      Case "7":  Text9.Text = "7 Thai"
      Case "8":  Text9.Text = "8 Hebrew (Lunar)"
      Case "9":  Text9.Text = "9 Gregorian Middle East French"
      Case "10": Text9.Text = "10 Gregorian Arabic calendar"
      Case "11": Text9.Text = "11 Gregorian Transliterated English"
      Case "12": Text9.Text = "12 Gregorian Transliterated French"
   End Select

  'Additional calendar type
   Select Case GetUserLocaleInfo(LCID, LOCALE_IOPTIONALCALENDAR)
      Case "0":  Text10.Text = "0 No additional types valid"
      Case "1":  Text10.Text = "1 Gregorian (localized)"
      Case "2":  Text10.Text = "2 Gregorian (English strings always)"
      Case "3":  Text10.Text = "3 Era: Year of the Emperor (Japan)"
      Case "4":  Text10.Text = "4 Era: Year of Taiwan Region"
      Case "5":  Text10.Text = "5 Tangun Era(Korea)"
      Case "6":  Text10.Text = "6 Hijri (Arabic lunar)"
      Case "7":  Text10.Text = "7 Thai"
      Case "8":  Text10.Text = "8 Hebrew (Lunar)"
      Case "9":  Text10.Text = "9 Gregorian Middle East French"
      Case "10": Text10.Text = "10 Gregorian Arabic calendar"
      Case "11": Text10.Text = "11 Gregorian Transliterated English"
      Case "12": Text10.Text = "12 Gregorian Transliterated French"
   End Select

  'Specifier for the first day in a week
   Select Case GetUserLocaleInfo(LCID, LOCALE_IFIRSTDAYOFWEEK)
      Case "0":  Text11.Text = "0   LOCALE_SDAYNAME1"
      Case "1":  Text11.Text = "1   LOCALE_SDAYNAME2"
      Case "2":  Text11.Text = "2   LOCALE_SDAYNAME3"
      Case "3":  Text11.Text = "3   LOCALE_SDAYNAME4"
      Case "4":  Text11.Text = "4   LOCALE_SDAYNAME5"
      Case "5":  Text11.Text = "5   LOCALE_SDAYNAME6"
      Case "6":  Text11.Text = "6   LOCALE_SDAYNAME7"
   End Select

  'Specifier for the first week of the year
   Select Case GetUserLocaleInfo(LCID, LOCALE_IFIRSTWEEKOFYEAR)
      Case "0":  Text12.Text = _
        "0 Week containing 1/1 is first week of that year"
      Case "1":  Text12.Text = _
        "1 First full week following 1/1 is first week of that year"
      Case "2":  Text12.Text = _
        "2 First week containing at least four days is first week of that year"
   End Select

End Sub



...
Рейтинг: 0 / 0
26.06.2014, 14:09
    #38680836
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Konst_One,

Ну, отлично.
Из всего что там нарисовано полезно вот это:Дмитрий772) Вычислить из настроек OS "ddd dd.MM.yyyy" (тупо формат как там забит) Вопрос как?
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
Public Declare Function GetUserDefaultLCID Lib "kernel32" () As Long

Public Const LOCALE_SSHORTDATE            As Long = &H1F    'short date format string
 
Public Declare Function GetLocaleInfo Lib "kernel32" _
 Alias "GetLocaleInfoA" _
 (ByVal Locale As Long, _
 ByVal LCType As Long, _
 ByVal lpLCData As String, _
 ByVal cchData As Long) As Long
'

Public Function GetShotDateFormat() As String
  Dim Locale As Long
  Locale = GetUserDefaultLCID
  
  Dim cch As Long
  Dim strBuf As String
  
  cch = GetLocaleInfo(Locale, LOCALE_SSHORTDATE, strBuf, 0)
  If cch > 0 Then
    strBuf = String(cch, 0)
    cch = GetLocaleInfo(Locale, LOCALE_SSHORTDATE, strBuf, cch)
    GetShotDateFormat = Left(strBuf, InStr(strBuf, Chr(0)) - 1)
  End If
End Function



Продвинулись на один шаг.
Можем написать свою CStr(As Date):

Код: vbnet
1.
2.
3.
4.
5.
6.
Public Function GetStrNowInCurrentFormat() As String
  GetStrNowInCurrentFormat = DateNowFormatted(GetUserDefaultLCID, GetShotDateFormat)
End Function

print GetStrNowInCurrentFormat
Чт 26.06.2014



Но мы занимаемся обратной задачей.
И остался вопрос:
Дмитрий773) обратный парсер dd->Число as Long, MM -месяц as Long Вопрос что за ф-ция?

Еще раз.
VarDateFromStr формат на вход не принимает, она его как-то внутренне вычисляет, но вычисляет дефолтный (а не тот, что мы сейчас успешно получили) и подсовывает ее в какую-то функцию-парсер , что намекает на существование таковой.

Т.е. требуется понять, что за ф-ция.
functionXXX (StringwithDate, ByVal lpFormat As String) As Date
либо
functionXXX (StringwithDate, ByVal lpFormat As String) As SYSTEMTIME

Ну, результат естественно out_ ByRef
...
Рейтинг: 0 / 0
26.06.2014, 15:01
    #38680919
Дмитрий77
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Формат даты и правильное его преобразование
Короче, это нерешаемая задача.
И что касается VarDateFromStr==CDate(As String), то все она делает правильно.
Я понял, она смотрит на КАСТОМИЗИРОВАННЫЕ настройки, а не на дефолтные.

Код: vbnet
1.
2.
3.
4.
dd\MM\yyyy -прокатит
dd\MM\yy -прокатит
ddd dd.MM.yyyy -не прокатит 
dd:MM:yyyy -не прокатит 'А как он поймет где там время, а где дата



Я хочу сказать, что не любые ДЕБИЛИЗИРОВАННО-КАСТОМИЗИРОВАННЫЕ настройки можно в принципе отпарсить (да еще и однозначно) в обратную сторону.

ddd dd.MM.yyyy -как раз из этой области.

Настенька Варианты: ... Ср01.01.2014 и т.д. (... без пробела) Как правильно его написать?
Ага, верх дебилизма. Если написать формат
ddddd.MM.yyyy, то он его даже в строку нормально не сконвертирует, куда уж там обратно.

Скажем так, на месте разработчиков виндов я бы тупо запретил подобную кастомизацию в принципе.
Там есть комбобокс, в выпадающем списке несколько разумных вариантов, которые парсятся туда и обратно без проблем, этого достаточно.
Все остальное - бред сивой кобылы.
И я вообще не понимаю,
какое отношение ddd dd.MM.yyyy имеет к КРАТКОМУ формату даты.

Блин, повелся, целый день на какую-то фигню потратил.
Тема раскрыта и закрыта.
...
Рейтинг: 0 / 0
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Формат даты и правильное его преобразование / 24 сообщений из 24, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]