Sorting Dictionary of Strings and Numbers - sorting

I have a dictionary object that needs to be sorted, but the keys are date values in the form
['Apr. 2013','May 2013','Feb. 2013',
'Mar. 2013','Jul. 2013','Aug. 2013',
'Sep. 2013','Oct. 2013','Jun. 2013','Nov. 2013']
As you can see, the dates are out of order. The corresponding value to each key is a number. I want to sort them in chronological order. However, since the months are string values, and since months are not alphabetically in order, I cannot just sort them automatically. Also, though not shown in the code sample, there may be years that are not 2013 as well. How would I go about sorting this dictionary?
Thanks in advance!

Code stolen from here:
Const csSep = "|"
Const cnMax = 100
Dim sInp : sInp = "Apr. 2013|May. 2013|Apr. 2014|Feb. 2013|Apr. 2011|Mar. 2013|Jul. 2013|Aug. 2013"
Dim aInp : aInp = Split(sInp, csSep) ' YourDic.Keys
WScript.Echo "A:", vbCrLf & Join(aInp, vbCrLf)
WScript.Echo "---------------------"
Dim oNAL : Set oNAL = CreateObject( "System.Collections.ArrayList" )
Dim oSB : Set oSB = CreateObject( "System.Text.StringBuilder" )
Dim sWord
For Each sWord In aInp
Dim dtCmp : dtCmp = CDate(sWord) ' depends on regional/locale settings
oSB.AppendFormat_3 "{0:yyyy-MM}{1}{2}", dtCmp, csSep, sWord
sWord = oSB.ToString()
oSB.Length = 0
oNAL.Add sWord
Next
oNAL.Sort
ReDim aOut(oNAL.Count - 1)
Dim i
For i = 0 To UBound(aOut)
aOut(i) = Split(oNAL(i), csSep)(1)
Next
WScript.Echo "B:", vbCrLf & Join(aOut, vbCrLf)
output:
A:
Apr. 2013
May. 2013
Apr. 2014
Feb. 2013
Apr. 2011
Mar. 2013
Jul. 2013
Aug. 2013
---------------------
B:
Apr. 2011
Feb. 2013
Mar. 2013
Apr. 2013
May. 2013
Jul. 2013
Aug. 2013
Apr. 2014
The theory is (c) R. L. Schwartz (see Schwartzian transform).
Update wrt Martha's answer (and my caveat):
Don't have to much confidence in VBScript's date conversions:
>> WScript.Echo CDate("Dez 2013")
>>
Error Number: 13 ' <-- can't read german
Error Description: Type mismatch
>> WScript.Echo CDate("Dec 2013") ' <-- can read english
>>
01.12.2013 ' <-- can write german
>> WScript.Echo DateValue("Dez 2013")
>>
Error Number: 13 ' <-- DateValue isn't more intelligent
Error Description: Type mismatch

The DateValue() function is pretty smart about recognizing dates, no matter how crazily they're formatted. It certainly has no trouble recognizing "Apr. 2013" as 4/1/2013. So in your sort routine, instead of comparing the keys, compare their DateValues.

I would replace each key with the respective formula:
newKey = year * monthRank
monthRank would be 1 for January, 2 for February and so on. newKey could then be used to sort every value. Of course this implys that you would have to parse the old keys in order to identify the monthRank and year, but converting the data from an unstructured data format to a sturctured one includes a cost you have to pay.
Hope I helped!

Related

Cannot convert my variables to CDate or Serial Date, getting Mismatch error [duplicate]

This question already has answers here:
UTC time stamp format - Split in parts a string containing the UTC time date (classic asp/vbscript)
(2 answers)
Closed 1 year ago.
I've ready numerous posts here about the mismatch error but every format I try I still get the same error.
Dim calendarDate, sDate, sFinal
calendarDate = "Sun Apr 05 00:00:00 CDT 2020"
sYear = Right(calendarDate, 4)
sDay = Mid(calendarDate,9,2)
sMonth = Mid(calendarDate,5,3)
If sMonth = "Apr" Then sMonth = "04" Else sMonth = sMonth
End if
sDate = sYear & "-" & sMonth & "-" & sDay
sFinal = CDate(sDate)
I get the type mismatch CDate error but the format should work? I have also tried MM/DD/YYYY.
And I have tried sFinal = DateSerial(sYear,sMonth,SDay) also does not work. But if you don't use the variables...
sFinal = DateSerial("2020","04","05") this works. I don't understand why my SYear, SMonth, SDay would not work as they are the same numbers."
My end goal here is to subtract 14 days from the calendar date but i can't even get my variable into a date format to subtract it...so maybe there is something simpler I should be doing here?
Thank you all for any help you can give much appreciated! Long time reader, first time posting.
The simplest way to manipulate will be to use Split() as each value separated by a Space (Chr(32)).
What you end up with is an array containing each element that made up the string split by the Space character (Chr(32)), so by concatenating values back together we can construct our date-time how CDate() expects, excluding the first and sixth element which will be Sun and CDT respectively, as well as re-ordering the year in the constructed string that is passed to CDate().
Dim input: input = "Sun Apr 05 00:00:00 CDT 2020"
Dim data: data = Split(input, Chr(32))
'Ignore first and sixth element in the array and build our date value
Dim output: output = CDate(data(1) & " " & data(2) & " " & data(5)) & " " & TimeValue(data(3))
Call Wscript.Echo(output)
Output:
05/04/2020 00:00:00
Note: Result will be based on the user's regional settings as CDate() uses this while parsing a Date string.
Useful Linkss
UTC time stamp format - Split in parts a string containing the UTC time date (classic asp/vbscript) (Example of parsing date string).

How to get month name 12 months back with asp classic?

I want to display the short name for each month, 12 months back from the previous month, but with the below I get an error on mon1 and mon2 and I guess since that is last year?
mon1=MonthName(Month(Now())-11,1)
mon2=MonthName(Month(Now())-10,1)
mon3=MonthName(Month(Now())-9,1)
mon4=MonthName(Month(Now())-8,1)
mon5=MonthName(Month(Now())-7,1)
mon6=MonthName(Month(Now())-6,1)
mon7=MonthName(Month(Now())-5,1)
mon8=MonthName(Month(Now())-4,1)
mon9=MonthName(Month(Now())-3,1)
mon10=MonthName(Month(Now())-2,1)
mon11=MonthName(Month(Now())-1,1)
mon12=MonthName(Month(Now()),1)
So how can I display now,dec,jan,feb,mar,apr,may,jun,jul,aug,sep,oct
Thanks.
The problem here is the Month() function returns an integer between 1 and 12 to represent each month. Instead you want to minus the number of months from the Now() value before wrapping it with Month().
Below is an example that does this using a For loop and a single dimension Array.
Dim dt: dt = Now()
Dim i, mon(12)
Const numOfMonths = 12
For i = 1 To numOfMonths
mon(i) = MonthName(Month(DateAdd("m", i - numOfMonths, dt)), True)
Next
Call Response.Write(Join(mon, vbCrLf))
Output:
Sep
Aug
Jul
Jun
May
Apr
Mar
Feb
Jan
Dec
Nov
Oct

How to add zero to single digit in a string

I need to to append zero in my below string whenever I get date with single digit without changing Quantity digit (below string is system generated in my application not created by user),
Data Added Quantity:1 on Dec 9 2015 modified on Jun 7 2016
I need to change this string just like below,
Data Added Quantity:125 on Dec 09 2015 modified on Jun 07 2016
So far I have tried the below regular expression, but not getting desired output.
str = "Data Added Quantity:1 on Dec 9 2015 modified on Jun 7 2016"
Set oReg = New RegExp
oReg.Pattern = "\s\d{1}\s"
Set obj = oReg.Execute(str)
For i = 0 To obj.Count-1
mD = obj.Item(i).Value
oReg.Replace(str, "0" & mD)
Next
How we can achieve this using VBScript?
If you adjust the pattern a little and set the Global option to True you can simply use the Replace method. No need to Excecute and loop.
Set re = New RegExp
re.Pattern = "\s(\d)\s"
re.Global = True
str = re.Replace(str, " 0$1 ")
\d without a modifier already matches exactly one digit, so \d{1} is redundant. The parentheses around the \d define a capturing group that allows you to use the matched substring in the replacement ($1).

SQL dates range conumdrum

I have a table date range that i'm retrieving with one date specified x_VisitDate
And four variables defined that will use the x_VisitDate
For this instance x_VisitDate = 22 May 2014 the download button should only be available 10 days prior to the given date as at today we are 7 days away.
x_TodaysDate
x_DaysBeForeToDownloadFile = 10
x_AdditionalDayToDownloadFile = 1
x_CanDownloadFile = DateAdd("d", x_DaysBeForeToDownloadFile , x_VisitDate)
x_ExtraCanDownloadFile = DateAdd("d", x_AdditionalDayToDownloadFile, x_VisitDate)
I'm currently writing the following
If x_CanDownloadFile <= x_TodaysDate then
and it's showing the file when the date is set for 21 Oct 2018 (Future) and 23 Feb 2014 (past)
I'm going crazy here...
thanks
Don't use comparisons to constructed limits, but DateDiff for range checks. It's much easier to get right. Demo code:
>> nDaysAvailable = 3
>> dtToday = Date
>> For i = -5 To 0
>> dtCheck = DateAdd("d", i, dtToday)
>> nDiff = DateDiff("d", dtCheck, dtToday)
>> WScript.Echo dtCheck, nDiff, CStr(nDiff < nDaysAvailable)
>> Next
>>
10.05.2014 5 False
11.05.2014 4 False
12.05.2014 3 False
13.05.2014 2 True
14.05.2014 1 True
15.05.2014 0 True
(german locale)
Maybe I'm confused by your question but can't you just do this?
x_VisitDate = #5/22/14#
If Date >= x_VisitDate - 10 And Date <= x_VisitDate + 1 Then
' Show file
End If
Also, you don' t need to use DateDiff() when you're working with days. Just use integer math.

How do I get the Date & Time (VBS)

How do I get the current date and time using VBS (for Windows. I'm not looking for VBScript for ASP/ASPX or webpages).
Here's various date and time information you can pull in vbscript running under Windows Script Host (WSH):
Now = 2/29/2016 1:02:03 PM
Date = 2/29/2016
Time = 1:02:03 PM
Timer = 78826.31 ' seconds since midnight
FormatDateTime(Now) = 2/29/2016 1:02:03 PM
FormatDateTime(Now, vbGeneralDate) = 2/29/2016 1:02:03 PM
FormatDateTime(Now, vbLongDate) = Monday, February 29, 2016
FormatDateTime(Now, vbShortDate) = 2/29/2016
FormatDateTime(Now, vbLongTime) = 1:02:03 PM
FormatDateTime(Now, vbShortTime) = 13:02
Year(Now) = 2016
Month(Now) = 2
Day(Now) = 29
Hour(Now) = 13
Minute(Now) = 2
Second(Now) = 3
Year(Date) = 2016
Month(Date) = 2
Day(Date) = 29
Hour(Time) = 13
Minute(Time) = 2
Second(Time) = 3
Function LPad (str, pad, length)
LPad = String(length - Len(str), pad) & str
End Function
LPad(Month(Date), "0", 2) = 02
LPad(Day(Date), "0", 2) = 29
LPad(Hour(Time), "0", 2) = 13
LPad(Minute(Time), "0", 2) = 02
LPad(Second(Time), "0", 2) = 03
Weekday(Now) = 2
WeekdayName(Weekday(Now), True) = Mon
WeekdayName(Weekday(Now), False) = Monday
WeekdayName(Weekday(Now)) = Monday
MonthName(Month(Now), True) = Feb
MonthName(Month(Now), False) = February
MonthName(Month(Now)) = February
Set os = GetObject("winmgmts:root\cimv2:Win32_OperatingSystem=#")
os.LocalDateTime = 20131204215346.562000-300
Left(os.LocalDateTime, 4) = 2013 ' year
Mid(os.LocalDateTime, 5, 2) = 12 ' month
Mid(os.LocalDateTime, 7, 2) = 04 ' day
Mid(os.LocalDateTime, 9, 2) = 21 ' hour
Mid(os.LocalDateTime, 11, 2) = 53 ' minute
Mid(os.LocalDateTime, 13, 2) = 46 ' second
Dim wmi : Set wmi = GetObject("winmgmts:root\cimv2")
Set timeZones = wmi.ExecQuery("SELECT Bias, Caption FROM Win32_TimeZone")
For Each tz In timeZones
tz.Bias = -300
tz.Caption = (UTC-05:00) Eastern Time (US & Canada)
Next
Source
To expound on Numenor's answer you can do something like, Format(Now(),"HH:mm:ss")
using these custom date/time formating options
For everyone who is tempted to downvote this answer please be aware that the question was originally tagged VB and vbscript hence my answer, the VB tag was edited out leaving only the vbscript tag. The OP accepted this answer which I take to mean that it gave him the information that he needed.
For VBScript use FormatDateTime, which has 5 numerical arguments to give you one of 5 predefined formats. Its not great.
FormatDateTime(now, 4)
08:12
This is an old question but alot of the answers in here use VB or VBA. The tag says vbscript (which is how I got here).
The answers here got kind of muddled since VB is super broad where you can have so many applications of it. My answer is solely on vbscript and accomplishes my case of formatting in YYYYMMDD in vbscript
Sharing what I've learned:
There are all the DateTime functions in vbscript defined here so you can mix-n-match to get the result that you want
What I needed was to get the current date and format it in YYYYMMDD to do that I just needed to concat DatePart like so for the current Date: date = DatePart("yyyy",Date) & DatePart("m",Date) & DatePart("d",Date)
That's all, I hope this helps someone.
Show time in form 24 hours
Right("0" & hour(now),2) & ":" & Right("0" & minute(now),2) = 01:35
Right("0" & hour(now),2) = 01
Right("0" & minute(now),2) = 35
nowreturns the current date and time
There are also separate Time() and Date() functions.

Resources