Announcement

Collapse
No announcement yet.

Date format correct

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    I didn't get that the OP was asking about DTP controls. OP said he uses a textbox. Sounds to me that OP is asking about parsing and formatting the text.

    Paul Squires once released EXCEL.INC, and it contains such a routine: CTOD()

    Here's Paul's copyright notice in the file:
    'Copyright (c) 2001 by Paul Squires.
    'Although this code is available for free, the author retains the copyright, which means that you
    'cannot do anything with it that is not expressly allowed by the author. In general terms, the author
    'would allow the programmer to incorporate the code into their applications. Selling the code by
    'itself is prohibited.
    so I don't think there's a problem with my copying it here. If so, moderators, please delete the code...

    Code:
    Function CTOD$(PBDate As String) 
    'ñññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
    'Converts a PowerBASIC formated date string into an xBase date
    ' Usage:   ans$ = CTOD("12-13-2001")
    '          ans$ = "20011213"
    'ñññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññññ
    'First parse PBDate
     Dim month$, day$, year$
     Dim ChekYear&
    
      month$ = Parse$(PBDate, Any "-", 1)     'month
      day$ = Parse$(PBDate, Any "-", 2)       'day
      year$ = Parse$(PBDate, Any "-", 3)      'year
    
      ChekYear& = Val(year$)
    
    ' Adjust if user enters only 2 digit year
       If ChekYear& < 80   Then     'assume we've rolled into the next century
          year$ = "20" + year$
       ElseIf ChekYear& < 100 Then   'between 1980 and 1999
          year$ = "19" + year$
       End If
    
    ' Force the reformat of strings into proper xBase length.
      month$ = Format$(Val(month$), "00")
      day$ = Format$(Val(day$), "00")
      year$ = Format$(Val(year$), "0000")
    
    
      Function = (year$ & month$ & day$)
    
    End Function
    This isn't exactly what was asked for, but minor editing will get it there.

    -John

    Comment


    • #22
      ..documentation On This function.
      Here's a starting point on MSDN
      Re: Not acting on Change - Maybe you could just use the NM_KILLFOCUS notification to signal when the User has done with editing / selecting the date info and is ready to move on?

      Here's a PBWin10 version inspired by Borje's sample. (It also shows another way to format the date info using the API GetDateFormat() - also courtesy of Paul Squires

      Code:
      #Dim All
      #Compile Exe                         ' PBWin10
      #Include "WIN32API.INC"
      #Resource Manifest, 1, "XPTheme.xml"
       
      %ID_LABEL     = 100
      %ID_BUTTON    = 101
      %ID_CALENDAR  = 102
       
      ' TT Paul Squires:  http://www.powerbasic.com/support/pb...d.php?t=040386
      Function FF_GetDate(TheDate As SYSTEMTIME, TheMask As String) As String
       Local zText As AsciiZ * %Max_Path
        '= Return New Formated Date Depending on the user's Selected Date Mask.
        GetDateFormat (%LOCALE_USER_DEFAULT, _            ' Locale
                      0, _                                ' dwFlags
                      ByVal VarPtr(TheDate), _            ' lpDate (SystemTime)
                      ByCopy TheMask, _                   ' lpFormat
                      zText, _                            ' lpDateString
                      SizeOf(zText))                      ' cchDate
       Function = zText
      End Function
      '------------------/FF_GetDate
       
      Function PBMain
       Local hDlg As Long
        Dialog New 0, "Calendar_2 demo.",,, 196, 60, %WS_SysMenu To hDlg
          Control Add Label, hDlg, %ID_LABEL, " Type date or click down arrow.. then TAB to advance.", 6, 30, 180, 14
          Control Add Button, hDlg, %ID_BUTTON, "&Done", 134, 6, 50, 14
          Control Add "SysDateTimePick32", hDlg, %ID_CALENDAR, "", 6, 6, 120, 14, %WS_Child Or _
                        %WS_TabStop Or %WS_Visible Or %DTS_LONGDATEFORMAT
        Dialog Show Modal hDlg Call DlgProc
      End Function
      '------------------/PBMain
       
      CallBack Function DlgProc()
       Local ST As SYSTEMTIME
         Select Case Cb.Msg
            Case %WM_InitDialog
       '       ' Preset date info if rqd - else defaults to current
       '        Local MyDate As SYSTEMTIME, hDTP As Dword
       '          Control Handle CB.HNDL, %ID_CALENDAR To hDTP
       '          MyDate.wYear = 1968 : MyDate.wMonth = 12 : MyDate.wDay = 25
       '          DateTime_SetSystemtime(hDTP, %GDT_VALID, MyDate)
      
             Case %WM_Command
              If Cb.Ctl = %IdCancel Then Dialog End Cb.Hndl, 0
              If Cb.Ctl = %ID_BUTTON Then WinBeep 800,100
       
            Case %WM_Notify
              If Cb.NmId = %ID_CALENDAR Then
                If Cb.NmCode = %NM_KillFocus Then           ' Get selected / edited date info
                  If DateTime_GetSystemtime(Cb.NmHwnd, ST) = %GDT_VALID Then
                    Control Set Text Cb.Hndl, %ID_LABEL, FF_GetDate(ST, "dddd, d MMMM yyyy")   ' Date Mask
                  End If
                End If
              End If
         End Select
      End Function
      '------------------/DlgProc
       
      #IF 0
        '   Mask elements
        ' d      Day Of month As digits With no leading zero For Single-digit days.
        ' dd     Day Of month As digits With leading zero For Single-digit days.
        ' ddd    Day Of week As a three-letter abbreviation. The Function uses the LOCALE_SABBREVDAYNAME value associated With the specified locale.
        ' dddd   Day Of week As its Full Name. The Function uses the LOCALE_SDAYNAME value associated With the specified locale.
        ' M      Month As digits With no leading zero For Single-digit months.
        ' MM     Month As digits With leading zero For Single-digit months.
        ' MMM    Month As a three-letter abbreviation. The Function uses the LOCALE_SABBREVMONTHNAME value associated With the specified locale.
        ' MMMM   Month As its Full Name. The Function uses the LOCALE_SMONTHNAME value associated With the specified locale.
        ' y      Year As last two digits, but With no leading zero For years less than 10.
        ' yy     Year As last two digits, but With leading zero For years less than 10.
        ' yyyy   Year represented by Full four digits.
       
       '  EG Return date based on today's date
       '   ? FF_GetDate( ByVal %Null, "yyyy-MM-dd")
       '   ? FF_GetDate( ByVal %Null, "MMM d, yyyy")
       
       #ENDIF
      Last edited by Dave Biggs; 2 Nov 2015, 08:31 AM.
      Rgds, Dave

      Comment


      • #23
        didn't get that the OP was asking about DTP controls. OP said he uses a textbox. Sounds to me that OP is asking about parsing and formatting the text.
        That is correct. Barry started with a plain text control. At least two of us are trying to persuade him to leave MS-DOS behind and go with a Windows' UI.

        I "like" the comment about a DTP being "inefficient." How the heck would you know until Susie User actually works with it?

        "Because we've always done it that way" applies to the user side of the user interface, too... where it is an equally poor reason to do something a certain way.

        You need to expect complaints ... people do not like any kind of change. In this case I'd suggest you provide the software with a DTP control and simply ignore the initial complaints or plead busy-ness because Susie will forget them quickly herself.

        Comment


        • #24
          Originally posted by Michael Mattias View Post
          I don't understand the part in the parentheses.....
          ...
          I must be missing something.
          In my case, the text input accepts a comma separated list of information. A "date field" is formatted as a date followed by a modifier. Something like this:

          2, 10/5/2015 Day Shift, 6

          ~~

          If parsing text input for date/time info fits your needs, the routine I referenced earlier works great. It adjusts for different locale settings as well (in case you have end users in various corners of the world).
          Bernard Ertl
          InterPlan Systems

          Comment


          • #25
            >In my case, the text input accepts a comma separated list of information.



            Minus ten (10) style points! No, make it twenty (20)!!



            (I only made those comments because it's not allowed for me to say "What a <equine excrement> design!)

            Comment


            • #26
              lol. UI is for the users, not the programmers. YMMV.
              Bernard Ertl
              InterPlan Systems

              Comment


              • #27
                > UI is for the users, not the programmers

                Um, Bern, programmers are there for the users. Think about it.

                Comment


                • #28
                  FWIW, my approach is to have two validation routines for each input field, on which is called on a change and one which is called on losing focus. So in a numeric date field, the changeproc will reject characters which are not numbers or solidi (or whatever the separator is), and the lostfocusproc will test the string as a valid date.

                  When the date can be entered as DDMONYYYY, the MON being an alpha string, the changeproc will reject alphabetic strings which cannot be found in the appropriate (eg English, Spanish) list of month abbreviations.

                  Add a few special keys, as needed. For example, HOME means today's date, numeric pad + and - adjust by one day backwards or forwards, and so on.

                  My apps are mostly used in commercial situations where throughput is of great concern, and every keystroke counts. Mouse clicks are just not fast enough. Pop-up calendars are seldom used.

                  Comment


                  • #29
                    >Mouse clicks are just not fast enough.

                    Fortunately the date-time picker control can be operated completely by keystroke.. mouse not required. Left-right arrows move between mon/day/year or whatever you set up; up/down arrows increment/decrement the portion of the date you are currently in.

                    Comment


                    • #30
                      Originally posted by Michael Mattias View Post
                      Fortunately the date-time picker control can be operated completely by keystroke.. mouse not required. Left-right arrows move between mon/day/year or whatever you set up; up/down arrows increment/decrement the portion of the date you are currently in.
                      If the date picker was around when I started the using kind of date input/validation which I described, I may well have used it, it would depend on exactly how many keystrokes would be needed to enter and change dates. BTW popping up a new dialog is distracting in itself. It takes time for an operator to self-train to ignore it.

                      Comment


                      • #31
                        If the date picker was around when I started the using kind of date input/validation which I described, I may well have used it,
                        My point Exactly.

                        I'll bet Barry would have, too.

                        Comment


                        • #32
                          Originally posted by Michael Mattias View Post
                          My point Exactly.
                          To get to your exact point, you had to ignore half my statement, but if you need it... you're welcome.

                          Comment


                          • #33
                            But if you really want to parse the text as per ..
                            .. had a routine, but all my source is blown... on CD's and maser file. Anyway, I let the user put in the date in a textbox in the form MM/DD/YYYY and haven't programmed in years and am having trouble. What I was doing was checking the entry (in a textbox) for two "/"'s and if not, the date is in the wrong format. Also, if only two characters past the last "/" means the year is put in at 2 digits and not 4. Then I check the month and day and month to see if it is earlier than today, if so the year must be next year, if no year is shown. If do add the prefix "20" to front of year. It seems that I was using a small routine to do this.
                            ... then the easy way might be to let Windows validate from your supplied month-day-year.

                            Code:
                            LOCAL st AS SYSTEMTIME 
                            
                                 ST.wYear   =  2000 + val(parsed_yy)
                                 ST.wMonth = 2000 + val (parsed_mm)
                                 ST.wDay    =  2000 + val (parsed_dd) 
                            
                                  bValid = ISValidDate (ST) 
                            
                            ..
                            
                            FUNCTION isValidDate (ST AS SYSTEMTIME) AS LONG  ' returns true/false
                              LOCAL ft As FileTime, ftnow As 
                              LOCAL stRef  AS SYSTEMTIME
                            
                              iRet = SystemTimeToFiletime ( ST, FT)   ' convert passed systemtyime to filetime
                               IF IsFalse iret THEN     ' function failed 
                                   FUNCTION = FALSE  ' either date invalid or something real bad is going on
                               ELSE
                                  ' because SystemTimeToFileTime will work with invalid dates like "10/32/2015" which is will return as  11/01/2015, you can check it.. 
                                   FileTimeToSystemTime  FT, STREF 
                                   IF (St.WYear = STRef.WYear) _  
                                      AND (St.Wmonth  = STRef.Wmonth) _  
                                      AND (St.Wday  = STRef.Wday)  _  
                                   THEN _ 
                                      FUNCTION = TRUE 
                                   ELSE
                                        FUNCTION = FALSE
                                   END IF
                            You can add an additional check that entered date is less than or equal to today using
                            Code:
                                  GetLocalTime stNow
                                  SystemTimetoFileTime stNow, FtNow 
                                  If CompareFileTime (ft, ftnow) <= 0 THEN  '  ft is less or equal to now 
                                     FUNCTION = true
                                  else
                                    FUNCTION= false
                                  END IF
                            NOTE: Function CompareFileTime MUST be DECLARED to return a LONG, not a DWORD for this to work.

                            But I still like the idea of going to a DTP control to replace the 'parsed free text' control.

                            MCM

                            Comment


                            • #34
                              When used with the %DTS_SHORTDATEFORMAT style, the DTP UI presents as a regular edit box - albeit one with a down arrow at one end.

                              It is not a requirement that the dropdown display of a Month Calendar Control be used - it's an extra but 'discreet' option.

                              The user is free to simply type in the data (with the DTP edit control vetting illegal entries on the fly).
                              Typed field entries are followed by any separator (,.-/: or space) to move to the next field. Movement between fields is automatic (wrapped if needed) and the TAB key can be used to complete an entry. No 'mousing about' required

                              For the more adventurous, navigation by use of the left and right arrow keys is available and the field values can be adjusted by use
                              of the up and down arrow keys.
                              Values can be changed incrementaly with the plus and minus keys or to upper or lower limits with the End and Home keys too.

                              By default the User's Locale determines the format of the date presentation in the DTP Edit control but that can be overridden by the programmer's preference.
                              The sequence of fields in the edit control, with or without separators, may be determined by entering a mask (aka string 'picture') applied with a
                              DateTime_SetFormat macro or by sending a DTM_SETFORMAT message to the control.
                              Here's another sample that enables experimentation with some of the options and demonstrates how a DTP control comfortably meets Barry's "MM/DD/YYYY" spec. - ok you do need to use 'MM/dd/yyyy'


                              Code:
                              #Compile Exe                                ' PBWin9^
                              #Dim All
                               '#Resource Manifest, 1, "XPTheme.xml"      ' (PBWin10)
                               '#Resource "DTP Test.pbr"                  ' PBWin905 "DTP Test.rc":   #include "Resource.h"
                              #Include "WIN32API.INC"                     '                           1 24 XPTheme.xml
                              #Include "COMMCTRL.INC"
                               
                              %ID_LABEL1   =  100
                              %ID_TEXTBOX1 =  101
                              %ID_BUTTON1  =  102
                              %ID_CALENDAR =  103
                              %ID_BUTTON   =  104
                              %ID_LABEL    =  105
                              %ID_TEXTBOX3 =  106
                              %ID_BUTTON3  =  107
                              %ID_LABEL3   =  108
                               
                              Function FF_GetDate(TheDate As SYSTEMTIME, TheMask As String) As String
                               Local zText As Asciiz * %Max_Path
                                '= Return New Formated Date Depending on the user's Selected Date Mask / String Pattern.
                                GetDateFormat (%LOCALE_USER_DEFAULT, _            ' Locale
                                              0, _                                ' dwFlags
                                              ByVal VarPtr(TheDate), _            ' lpDate (SystemTime)
                                              ByCopy TheMask, _                   ' lpFormat
                                              zText, _                            ' lpDateString
                                              SizeOf(zText))                      ' cchDate
                               Function = zText
                              End Function
                              '------------------/FF_GetDate
                               
                              CallBack Function DlgProc()
                               Local ST As SYSTEMTIME, szTemp As Asciiz * 80
                                Select Case As Long CB.Msg
                                  Case %WM_InitDialog
                                    Static hDTP As Dword, sOutFormat As String, sDTPInFormat As String
                                    Control Handle CB.Hndl, %ID_Calendar To hDTP
                                    GetLocaleInfo(%LOCALE_USER_DEFAULT, %LOCALE_SSHORTDATE, szTemp, 80)   ' get Locale shortdate format
                                    sDTPInFormat = szTemp : sOutFormat = szTemp
                                    szTemp += " (= LOCALE_SSHORTDATE)"
                                    Control Set Text CB.Hndl, %ID_LABEL1, szTemp
                               '     Local MyDate As SYSTEMTIME                                           ' set initial date if required (default is Now)
                               '      MyDate.wYear = 1968 : MyDate.wMonth = 12 : MyDate.wDay = 25
                               '      DateTime_SetSystemtime(hDTP, %GDT_VALID, MyDate)
                               
                                  Case %WM_Command
                                    Select Case As Long CB.Ctl
                                      Case %ID_BUTTON1
                                        If CB.CtlMsg = %BN_Clicked Then                                   ' modify DTP input mask / 'string picture'
                                          Control Get Text CB.Hndl, %ID_TEXTBOX1 To szTemp
                                          DateTime_SetFormat(hDTP, szTemp)
                                          sDTPInFormat = szTemp
                                        End If
                                      Case %ID_BUTTON                                                     ' Accept input
                                        If CB.CtlMsg = %BN_Clicked Then
                                          Dialog Send CB.Hndl, %WM_NEXTDLGCTL, hDTP, 1                    ' demo just sets focus back on DTP control
                                        End If
                                      Case %ID_BUTTON3                                                    ' set format of output string as required
                                        If CB.CtlMsg = %BN_Clicked Then
                                          Control Get Text CB.Hndl, %ID_TEXTBOX3 To szTemp
                                          sOutFormat = szTemp
                                          If DateTime_GetSystemtime(hDTP, ST) = %GDT_VALID Then
                                            Control Set Text CB.Hndl, %ID_LABEL, FF_GetDate(ST, sOutFormat)   ' Date Mask
                                          End If
                                        End If
                                    End Select
                               
                                      Case %WM_Notify
                                        If CB.NmId = %ID_CALENDAR Then
                                          If CB.NmCode = %NM_KillFocus Then                               ' Get selected / edited date info
                                            If DateTime_GetSystemtime(CB.NmHwnd, ST) = %GDT_VALID Then
                                              Control Set Text CB.Hndl, %ID_LABEL, FF_GetDate(ST, sOutFormat)   ' Date Mask
                                            End If
                                          End If
                                        End If
                               
                                End Select
                              End Function
                              '------------------/DlgProc
                               
                              Function PBMain As Long
                               Local hDlg As Dword
                               
                                Dialog New 0, "DTP MM/dd/yyyy test.", 200, 100, 200, 130, %WS_SysMenu Or %WS_Caption To hDlg
                                  Control Add Label,   hDlg, %ID_LABEL1, "Use top edit box to set date format in DTP control", 15, 30, 175, 15
                                  Control Add TextBox, hDlg, %ID_TEXTBOX1, "DTP Pattern", 10, 10, 120, 15
                                  Control Add Button,  hDlg, %ID_BUTTON1, "Apply ", 140, 10, 50, 15
                                  Control Add "SysDateTimePick32", hDlg, %ID_CALENDAR, "", 10, 50, 120, 15, %WS_Child Or %WS_Visible _
                                                Or %WS_TabStop Or %DTS_SHORTDATEFORMAT
                                  Control Add Button,  hDlg, %ID_BUTTON, "Accept", 140, 50, 50, 15
                                  Control Add Label,   hDlg, %ID_LABEL, "Display results here when DTP looses focus", 15, 70, 175, 15
                                  Control Add TextBox, hDlg, %ID_TEXTBOX3, "O/P Pattern", 10, 90, 120, 15
                                  Control Add Button,  hDlg, %ID_BUTTON3, "Apply", 140, 90, 50, 15
                                  Control Add Label,   hDlg, %ID_LABEL3, "Change output pattern. eg dddd, MMMM d yyyy", 15, 110, 175, 15
                               
                                Dialog Show Modal hDlg, Call DlgProc
                              End Function
                              '------------------/PBMain
                               
                              #IF 0
                              '==================================================================================================
                              
                               ' Date Time Picker Control: https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx
                              ' TT Borje                  http://www.powerbasic.com/support/pb...d.php?t=022608
                              ' TT Paul Squires:          http://www.powerbasic.com/support/pb...d.php?t=040386
                                
                                '   Mask elements
                                ' d      Day Of month As digits With no leading zero For Single-digit days.
                                ' dd     Day Of month As digits With leading zero For Single-digit days.
                                ' ddd    Day Of week As a three-letter abbreviation. The Function uses the LOCALE_SABBREVDAYNAME value associated With the specified locale.
                                ' dddd   Day Of week As its Full Name. The Function uses the LOCALE_SDAYNAME value associated With the specified locale.
                                ' M      Month As digits With no leading zero For Single-digit months.
                                ' MM     Month As digits With leading zero For Single-digit months.
                                ' MMM    Month As a three-letter abbreviation. The Function uses the LOCALE_SABBREVMONTHNAME value associated With the specified locale.
                                ' MMMM   Month As its Full Name. The Function uses the LOCALE_SMONTHNAME value associated With the specified locale.
                                ' y      Year As last two digits, but With no leading zero For years less than 10.
                                ' yy     Year As last two digits, but With leading zero For years less than 10.
                                ' yyyy   Year represented by Full four digits.
                                
                               '  EG Return date based on today's date
                               '   ? FF_GetDate( ByVal %Null, "yyyy-MM-dd")
                               '   ? FF_GetDate( ByVal %Null, "MMM d, yyyy")
                               
                               #EndIf
                              Attached Files
                              Last edited by Dave Biggs; 10 Nov 2015, 08:02 AM. Reason: sp
                              Rgds, Dave

                              Comment

                              Working...
                              X