Change the max and min date in CultureInfo - vb.net

Is it possible to change the max and min date for a DateTimePicker using CultureInfo("ar-SA") or any Culture in general?
This the sample code that changes the Culture:
Dim CultureInfo As CultureInfo
CultureInfo = New CultureInfo("ar-SA")
CultureInfo.DateTimeFormat.Calendar = New System.Globalization.GregorianCalendar
Thread.CurrentThread.CurrentUICulture = CultureInfo
Application.CurrentCulture = CultureInfo
If a new window containing a DateTimePicker (DTP) is then opened, that DTP has:
.MinDate = 1900-04-30
.MaxDate = 2077-11-16
Without setting the CultureInfo, the values for the DTP are
.MinDate = 1753-01-01
.MaxDate = 9998-12-31
Trying to set the DTP.MinDate to New DateTime(1800, 1, 1) gives an error of:
DateTimePicker does not support dates before 04/30/1900 12:00:00 ص.
and trying to set the DTP.MaxDate to New DateTime(2100, 1, 1) gives an error of:
DateTimePicker does not support dates after 12/31/9998 12:00:00 ص.
Also, note the discrepancy in the year in the latter case.

The problem is fixed by adding this line: ''' Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US") '''

Related

How to compare Time variables?

I have 3 variables of type DateTime or string type, in the form hh:mm:ss.
For example:
dT1="00:00:00"
dT2="20:59:59"
dT3="18:04:21"
How can I perform the following comparison?
dT1<= dT3 <= dT2 ??
Your example show String not DateTime. I put your strings in and array called TimeStrings. Then I created a List of TimeSpan. Looping through the strings I split each string on the colon, then created a new TimeSpan and added it to the list. I used the .Max method of the list to get the highest value in the list.
Private Sub OpCode()
'Constructor TimeSpan(Int32, Int32, Int32)
Dim dT1 = "00:00:00"
Dim dT2 = "20:59:59"
Dim dT3 = "18:04:21"
Dim TimeStrings = {dT1, dT2, dT3}
Dim Spans As New List(Of TimeSpan)
For Each s In TimeStrings
Dim Splits = s.Split(":"c)
Dim span As New TimeSpan(CInt(Splits(0)), CInt(Splits(1)), CInt(Splits(2)))
Spans.Add(span)
Next
Dim HighestValue = Spans.Max
MessageBox.Show(HighestValue.ToString)
End Sub
You can use the TimeSpan.Parse(), ParseExact(), TryParse() or TryParseExact() to convert the string to a TimeSpan value. The comparison is straightforward after that:
Add your string values to a collection (an Array or List of strings).
Dim dTs As String() = {"00:00:00", "23:59:59", "20:59:59", "23:10:21", "18:04:21"}
Dim max As TimeSpan = dTs.Select(
Function(s) TimeSpan.ParseExact(s, "hh\:mm\:ss", CultureInfo.InvariantCulture)).Max()
max will be 23:59:59
Of course you can order the TimeSpan value, in ascending order here:
Dim orderedTimeSpans =
dTs.Select(Function(s) TimeSpan.ParseExact(s, "hh\:mm\:ss", CultureInfo.InvariantCulture)).
OrderBy(Function(ts) ts).ToList()
orderedTimeSpans.ForEach(Sub(ts) Console.WriteLine(ts))
Which prints:
00:00:00
18:04:21
20:59:59
23:10:21
23:59:59
With TryParseExact(), if you're not sure whether the format is may not be correct (possibly, because the source of the values is not reliable - User input, for example):
Dim parsed As TimeSpan
Dim max As TimeSpan =
dTs.Select(Function(s) TimeSpan.TryParseExact(s, "hh\:mm\:ss",
CultureInfo.InvariantCulture, parsed)).Max(Function(t) parsed)
This also returns 23:59:59.
If one of the values cannot be parsed, it won't be evaluated by the Max() method.
E.g., if this is the input string "23.59:59", InvariantCulture and the format specified won't allow to return a valid TimeSpan, so the max value will be 23:10:21 instead.
The same, using TryParseExact(), but in extended form (using a loop):
Dim maxValue As TimeSpan = New TimeSpan()
Dim parsed As TimeSpan = New TimeSpan()
For Each value As String In dTs
If TimeSpan.TryParseExact(value, "hh\:mm\:ss", CultureInfo.InvariantCulture, parsed) Then
maxValue = If(TimeSpan.Compare(maxValue, parsed) > 0, maxValue, parsed)
End If
Next
You can try something like this:
Dim dT1 As DateTime = New DateTime(2020, 1, 1, 0, 0, 0) ' 00:00:00
Dim dT2 As DateTime = New DateTime(2020, 1, 1, 20, 59, 59) ' 20:59:59
Dim dT3 As DateTime = New DateTime(2020, 1, 1, 18, 04, 21) ' 18:04:21
If dT1 <= dT3 <= dT2 Then
'your code
End If
Hope, it helps :)

vb.net timeadding from two textbox

Please help me first before giving me a bad feedback.
I need to add two time from text box. But when I'm adding it only the minute was adding and not the hours.
Dim dt As DateTime = TxtDTEAP.Text
Dim wt As DateTime = TxtWTEAP.Text
Dim totalspan As New TimeSpan
Dim result As New DateTime
result = dt.AddMinutes(wt.Minute)
Me.TxtTRTEAP.Text = result
For example, the txtWTEAP.Text = 1:30 and txtDTEAP.Text = 2:50 the result should be 4:20 but the result showing on this code is 1:20 only.
Thank you so much!
Split the strings in the TextBoxes into an array. The first element will contain the hours and the second element will contain the minutes. The c following the split character tells the compiler this is a char not a string.
Use the constructor of the TimeSpan structure to create TimeSpans. The constructor takes 3 arguments, Hours as Integer, Minutes as Integer and Seconds as Integer.
Finally, we can do the addition.
Then display the result using .ToString with a format string. The \ is and escape character so it doesn't think the : is something else.
Private Sub GetTotalTime()
Dim parseTime1() As String = TxtDTEAP.Text.Split(":"c)
Dim parseTime2() As String = TxtWTEAP.Text.Split(":"c)
Dim dt As TimeSpan = New TimeSpan(CInt(parseTime1(0)), CInt(parseTime1(1)), 0)
Dim wt As TimeSpan = New TimeSpan(CInt(parseTime2(0)), CInt(parseTime2(1)), 0)
Dim result As TimeSpan = dt + wt
TxtTRTEAP.Text = result.ToString("h\:mm")
End Sub

How to count no. of days between 2 dates from calendar in string format vb

I have 2 aspx calendar(AbsenceStartDateCal & AbsenceEndDateCal) which will pass the date value to textbox with .cs codes as follow:
Protected Sub AbsenceEndDateCal_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles AbsenceEndDateCal.SelectionChanged
Dim date2 As DateTime = New System.DateTime
date2 = AbsenceEndDateCal.SelectedDate
tbAbsenceEndDate.Text = date2.ToString("dd/MM/yyyy")
End Sub
In my pageload, i want to count no.of days to display as a label btw the 2 textbox value. I tried with the following code but it doesn't work with this error "String was not recognized as a valid DateTime."
Dim startDate As DateTime = Convert.ToDateTime(tbAbsenceStartDate.Text)
Dim endDate As DateTime = Convert.ToDateTime(tbAbsenceEndDate.Text)
Dim ts As New TimeSpan
ts = endDate.Subtract(startDate)
lblnoOfDays.Text = ts.Days
So i am not sure cos im new to VB. Any help would be greatly appreciated.
You can use ParseExact method and specify the formatting you want.
You get invalid formatting because you are probably trying to set day or month values which exceed the range defined under the current formatting.
Example:
Dim startDateString = "12/01/2015"
Dim endDateString = "14/01/2015"
Dim startDate = DateTime.ParseExact(startDateString, "dd/mm/yyyy", CultureInfo.InvariantCulture)
Dim endDate = DateTime.ParseExact(endDateString, "dd/mm/yyyy", CultureInfo.InvariantCulture)
Dim ts As New TimeSpan
ts = endDate.Subtract(startDate)
Dim dayDiff = ts.Days

How do I make the closest future date to today's date the default dropdownlist value?

We dynamically populate our dropdownlist with several event dates from the database.
Currently, all dates less than today's date are disabled and can't be viewed by our users.
The next available date greater than today's date becomes the default dropdownlist value and all future dates are avaiable and visible in the dropdownlist.
For instance, if we have the following dates on our datebase:
2/12/2013
12/20/203
5/21/2014
8/8/2014
10/22/2014
since three of the dates (2/12/2013,12/20/203,5/21/2014) are less than today's date, these dates are disabled and not viewable.
The closest available date greater than today's date is 8/8/2014 and this becomes the default dropdownlist value.
Finally all future dates like 10/22/2014 are also available in the dropdownlist.
Here are the code snips that make this happen:
//the markup
<asp:DropDownList id="txtEventDate" runat="server">
</asp:DropDownList>
//Code that dynamically populates dropdownlist
Dim cmd As New SqlCommand("Select convert(datetime, dates, 103) dates, CONVERT(VARCHAR(12), dates, 107) as datelist from events", New SqlConnection(ConfigurationManager.ConnectionStrings("Events").ConnectionString))
cmd.Connection.Open()
Dim ddlValues As SqlDataReader
ddlValues = cmd.ExecuteReader()
txtEventDate.DataSource = ddlValues
txtEventDate.DataValueField = "dates"
txtEventDate.DataTextField = "datelist"
txtEventDate.DataBind()
cmd.Connection.Close()
cmd.Connection.Dispose()
//Code that displays only future dates with next available future date as default dropdownlist value
For Each items As ListItem In txtEventDate.Items
If (DateTime.Parse(items.Value).CompareTo(DateTime.Today)) < 0 Then
items.Enabled = False
End If
Next
Our users would like to change the process so they would be allowed to go back to an older date and make some changes if they needed to.
Any ideas how to address this problem?
Public Sub PopulateDates()
Dim cmd As New SqlCommand("Select convert(datetime, dates, 103) dates, CONVERT(VARCHAR(12), dates, 107) as datelist from events", New SqlConnection(ConfigurationManager.ConnectionStrings("events").ConnectionString))
cmd.Connection.Open()
Dim lstDates As New List(Of DateTime)()
Using rdr As SqlDataReader = cmd.ExecuteReader()
If rdr.Read() Then
lstDates.Add(DirectCast(rdr("dates"), DateTime))
End If
End Using
lstDates = lstDates.OrderBy(Function(x) x.[Date]).ToList()
Dim nearestDate = lstDates.OrderBy(Function(t) Math.Abs((t - DateTime.Now).Ticks)).First()
txtEventDate.DataSource = lstDates
txtEventDate.DataBind()
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString()))
cmd.Connection.Close()
cmd.Connection.Dispose()
End Sub
Per your comment it seems like you want to let the user change the older dates. So remove your For Each that disables the older dates.
First you need to find the nearest date equal or closer to current date like below
Dim nearestDate = ddlValues.OrderBy(Function(t) Math.Abs((t.dates - DateTime.Now).Ticks)).First()
Then after you do the data binding keep the nearest date default selected using FindByValue or FindByText
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString()))
Side Note: always try using using statements for your db connection objects like SqlConnection, SqlCommad etc so the resources used by these objects are freed up after usage.
UPDATE 1: Based on what you reported in your comment, I made few changes as to the date format ( it was not part of your initial question) etc and here is the complete code for PopulateDates(). Also make sure you don't run the foreach you earlier had to set the nearest date because it might set wrong values. If you get wrong values then better put breakpoint and see which object returns unexpected data.
Public Sub PopulateDates()
Dim cmd As New SqlCommand("Select dates from events", New SqlConnection(ConfigurationManager.ConnectionStrings("events").ConnectionString))
cmd.Connection.Open()
Dim lstDates As New List(Of DateTime)()
Using rdr As SqlDataReader = cmd.ExecuteReader()
If rdr.Read() Then
lstDates.Add(DirectCast(rdr("dates"), DateTime))
End If
End Using
Dim stDates As List(Of [String]) = lstDates.OrderBy(Function(o) o.[Date]).[Select](Function(x) x.[Date].ToString("MMM dd, yyyy")).ToList()
Dim nearestDate = lstDates.OrderBy(Function(t) Math.Abs((t - DateTime.Now).Ticks)).First()
// Dim nearestDate = lstDates.First(Function(x) x >= DateTime.Now.[Date]) // this does the trick too
txtEventDate.DataSource = stDates
txtEventDate.DataBind()
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString("MMM dd, yyyy")))
cmd.Connection.Close()
cmd.Connection.Dispose()
End Sub
Here is the link to the DEMO (unfortunately it's in C#) I set up to show how it return me the correct data.
UPDATE 2: Here is your complete working version (hopefully it works). I tried this locally to load the data from database and retrieving through the DataReader and everything works the way you wanted.
You reported in your comment saying only one item was returned when accessing from the DataReader, it's because your original code had If rdr.Read() Then which will exit after the first record but rather we need to use while to iterate the complete list.
Regarding Value field and Text of the dropdownlist holding different date format, I've created a Dictionary collection to achieve this. Here is your complete code for PopulateDates().
Public Sub PopulateDates()
Dim cmd As New SqlCommand("Select dates from events order by dates", New SqlConnection(ConfigurationManager.ConnectionStrings("events").ConnectionString))
cmd.Connection.Open()
Dim list As New Dictionary(Of String, DateTime)()
Using rdr As SqlDataReader = cmd.ExecuteReader()
Dim dt As DateTime
While rdr.Read()
dt = DateTime.Parse(rdr("dates").ToString())
list.Add(dt.ToString("MM/dd/yyyy"), dt)
End While
End Using
txtEventDate.DataSource = list
txtEventDate.DataTextField = "Value"
txtEventDate.DataValueField = "key"
txtEventDate.DataTextFormatString = "{0:MMM dd, yyyy}"
txtEventDate.DataBind()
Dim nearestDate = list.First(Function(x) x.Value >= DateTime.Now.[Date]).Key
txtEventDate.SelectedIndex = txtEventDate.Items.IndexOf(txtEventDate.Items.FindByValue(nearestDate.ToString()))
cmd.Connection.Close()
cmd.Connection.Dispose()
End Sub
And the HTML markup looks like the format you wanted.
Totally untested, but would something like the following do what you want? Your list of items will need to be sorted, if it's not already, but this should find the first item that is for today or later and set it as the selected item in the drop-down.
Update - try SelectedValue instead!
For Each items As ListItem In txtEventDate.Items
If (DateTime.Parse(items.Value).CompareTo(DateTime.Today)) >= 0 Then
txtEventDate.SelectedValue = items.Value
Exit For
End If
Next

Textbox date to database

I have the following code which worked fine on a .net 1.1 website:
objSQLCommand.Parameters.Add(New SqlParameter("#date", SqlDbType.DateTime, 8))
objSQLCommand.Parameters("#date").Value = txtDate.Text
This doesn't work on a .net 3.5 server.
I'm getting a message saying that it can't convert a string to datetime.
Try this one,
objSQLCommand.Parameters("#date").Value = Convert.ToDate(txtDate.Text)
follow-up question, what is the format of the date in your textbox? Maybe you can take advantage of TryParse or ParseExact also.
Dim provider As CultureInfo = CultureInfo.InvariantCulture
Dim dateString as String = txtDate.Text '08/10/2012
Dim format As String = "d"
objSQLCommand.Parameters("#date").Value = Date.ParseExact(dateString, format, provider)