I'm trying to delete files that are more than six months old. This is my code. It recognizes the files, but does not delete.
Private Sub DeleteOldBackup()
'deletes files older than six months from backup
Try
For Each fi As IO.FileInfo In New IO.DirectoryInfo(BACKUP).GetFiles()
If DateDiff(DateInterval.Month, Now, fi.CreationTime) > 6 Then
fi.Delete()
End If
Next
Catch ex As Exception
Call WriteToErrorLog("DeleteOldBackup", ex)
SendErrorEmail("Long Term Report Storage failed in DeleteOldBackup")
End Try
End Sub
DateDiff subtracts from the second date the first date. Passing the highest date in the first position returns a negative number.
Just swap the positions of the two dates
If DateDiff(DateInterval.Month, fi.CreationTime, Now ) > 6 Then
Keep also present that this calculation is wrong. For example
Dim d1 = new DateTime(2014,1,1)
Dim x = DateDiff(DateInterval.Month, d1, Now)
Console.WriteLine(x)
The code above prints 6 but actually there are more than 6 months between the first of january and today. Perhaps you should use DateInterval.Day and check against something like 180 days to have a better approximation of 6 months
Related
I'm using the BaselineWork1 timescaledata to contain a time phased calculation of resource work on individual tasks that I perform on a weekly basis. I want to zero out the previous week's calculation before I populate it with this week's calculation. Short of creating a loop to write zeros to the timescale data for each resource on each task is there a way to do this more efficiently? Could I make the beginning date and end date equal to the project's start and end date and time scale = seconds and the value to write equal to zero? For instance:
For lngCnt1 = 1 To tskCounter.Resources.Count
tskCounter.Assignments.Item(lngCnt1).TimeScaleData(StartDate:=ActiveProject.ProjectStart, EndDate:=ActiveProject.ProjectFinish, _
Type:=pjAssignmentTimescaledBaseline1Work, _
timescalunit:=pjTimescaleMinutes, Count:=1).Item(1).Value = 0
Next lngCnt1
This doesn't seem to work as it only zeros out the baseline1 work field for the date corresponding to the project start date.
To clear time-scaled work from anything but the forecast work field, you do need to loop through every assignment on every task. However, when it comes to the individual time-scale values, you can lump these together by year to reduce the iterations required.
Sub ClearBaseline1Work()
Dim projStart As Date
Dim projEnd As Date
projStart = ActiveProject.ProjectStart
projEnd = ActiveProject.ProjectFinish
Dim tsk As Task
For Each tsk In ActiveProject.Tasks
Dim asn As Assignment
For Each asn In tsk.Assignments
Dim TSValues As TimeScaleValues
Set TSValues = asn.TimeScaleData(projStart, projEnd, pjAssignmentTimescaledBaseline1Work, pjTimescaleYears)
Dim tsv As TimeScaleValue
For Each tsv In TSValues
tsv.Clear
Next tsv
asn.Baseline1Work = 0
Next asn
tsk.Baseline1Work = 0
Next tsk
End Sub
Remember that Baseline1 work values are not automatically updated at the assignment or task level; those values need to be explicitly cleared.
I have created a text file with dates and products bought on that date. I want to read the file when a button is clicked and the return the products bought on the current date only (todays date) into a listbox in VB.net . Any help appreciated.
This is an example of my textfile.
06:35 Sunday, 15 March 2015
Corona Bottle
Miller Bottle
Bulmers Bottle
Beamish Pint
Bacon Fries
Orange Juice
06:41 Sunday, 15 March 2015
Murphy's Pint
Bulmers Pint
Tayto
Purple Snack
This is the code that i have so far:
Private Sub btnTodaysTrans_Click(sender As Object, e As EventArgs) Handles btnTodaysTrans.Click
Dim sr As IO.StreamReader = IO.File.OpenText("ProductsSold.txt")
lstTodaysTrans.Items.Clear()
Do While sr.Peek <> -1
lstTodaysTrans.Items.Add(sr.ReadLine)
Loop
sr.Close()
End Sub
try using the textparser for your operation.it will be like
dim field as string
dim date as datetime
If File.Exists(yourfilename) Then
Using parser As New TextFieldParser(yourfilename)
parser.SetDelimiters(vbTab)
While Not parser.EndOfData
fields = parser.ReadFields()
if IsDate(fields) Then
date= DateTime.ParseExact(fields, "yyyy-MM-dd HH:mm tt", System.Globalization.CultureInfo.InvariantCulture)
if date.value<> your condition Then
'' what you want
else
''what you want
end if
end if
end while
end if
NOTE
Or else You can use the error encountered while converting the text files to datetime as condition for checking if it is a valid date.
First, that is a bad way to store your data. The best way is a database. But even if you use a text-file you could use a better approach. Because the file contains empty line and also different lines belong logically together. So you need to find the date of every product in the previous lines. You could add it to every line, then it's easier.
However, you can use following code which uses LINQ and a loop:
Dim format = "dd MMMM yyyy"
Dim dateProducts As New List(Of Tuple(Of Date, String))
Dim lines = From line In File.ReadLines("ProductsSold.txt")
Where Not String.IsNullOrWhiteSpace(line)
Select line.Trim()
For Each line As String In lines
Dim currentDate As Date
Dim isDateline As Boolean = False
If line.Length >= format.Length AndAlso line.Contains(","c) Then
' try to extract the date...
Dim tokens = line.Split({","c}, StringSplitOptions.RemoveEmptyEntries)
isDateline = Date.TryParseExact(tokens.Last().Trim(), format, CultureInfo.InvariantCulture, DateTimeStyles.None, currentDate)
End If
If isDateline Then
dateProducts.Add(New Tuple(Of Date, String)(currentDate, Nothing))
ElseIf dateProducts.Count > 0 Then
' select date from last item and add this product
dateProducts.Add(New Tuple(Of Date, String)(dateProducts.Last().Item1, line))
Else
' otherwise invalid data, product without date, skip
End If
Next
Now you could use ToLookup to create something similar to a dictionary, the key is the date(without time) and the value is the list of products for that date. One difference to a dictionary is that you get an empty sequence if there is no product for a given date.
Dim dateLookup = dateProducts.
Where(Function(ds) ds.Item2 IsNot Nothing).
ToLookup(Function(ds) ds.Item1.Date)
Dim allProductsOfToday = dateLookup(Date.Today)
For Each dateProductInfo In allProductsOfToday
lstTodaysTrans.Items.Add(dateProductInfo.Item2) ' Item2 is the product
Next
I have tested it with your sample file which doesn't contain products for today, so it's not the best example. If you change one of both date from 15 March 2015 to 16 March 2015 you see the appropriate products in the ListBox.
I have 3 textboxes (day, month, year) and I want to check if input is e.g. day has to be from 1 to 31 and so on.
My code is:
If InputDan.Text < "1" Or InputDan > "31" Then Warning.Text = "Not a valid day input." Else Warning.Text = ""
Also I have day and month input limited to 2 characters and year to 4.
It works fine with numbers from 10 to 31 and it properly puts an warning message when input is 0 or 32 and on.
Here's the problem...
When I put in numbers from 4 to 9 it puts on a warning message, as I figured out later that program considers empty space after one character input as 0.
So if I enter 4 the program will read it as 40, and so on.
Can I solve this problem with converting String input as Int somehow?
You need to parse the numbers to integer before you can compare them, otherwise >"11" will compare them alphabetically and not by their numerical order.
Dim day As Integer
Dim valid As Boolean = Int32.TryParse(InputDan.Text, day)
Now you know if that input was a correct number and you could show a warning if it was not.
I would suggest a different approach to check whether or not the input was a correct day since you must take the number of days in that month into account(also leap years, different calendars etc). So use the current culture's calendar and look if the number of days is correct for the given month in this way:
Dim daysInMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(year, month)
If day > daysInMonth OrElse day < 1 Then
' show warning '
End If
(assuming you have already checked the year and month part with Int32.TryParse)
Better than doing this from the code behind, asp.net has already validations here is an example of a textbox that represents the day, and it has to be between 1 and 31:
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RangeValidator ID="RangeValidator1" runat="server"
ErrorMessage="You have to insert a valid day" ControlToValidate="TextBox2" MaximumValue="31" MinimumValue="1"></asp:RangeValidator>
check it out
Your problem is, that "9" (the string) IS "larger" than "31". Because sorting is done on the first char, then the second and so on.
Dim Value As Integer
' is there an (integer) NUMBER in the textbox?
If Integer.TryParse(InputDan.Text, Value) Then
If Value > 0 AndAlso Value < 31 Then
' do something
Else
MessageBox.Show("please enter a number!")
End If
Else
MessageBox.Show("please enter a number!")
End If
With "TryParse" you can test if a String can be converted to an Integer (or Double, Single, whatever implements a TryParse method) and if it can be converted, the value is stored in the second parameter.
You should use Strict on" to avoid the coding problems - basically you are comparing strings against each other. They do NOT behave like Integers for comparisons.
Try like this: (Assuming framework above/or 3.5)
If Not IsNumeric(InputDan.Text) OrElse _
Not Enumerable.Range(1, 31).Contains(CInt(InputDan.Text)) Then
Warning.Text = "Not a valid day input."
Else
Warning.Text = ""
End If
It will first validate the input must be a number and then will validate if it lies within range of 1 and 31. I assume Days can not be 1.5 so I called CInt.
OrElse is what we call ShortCircuit. The second condition will not evaluate if the first one failed.
Long story short:
I need the inverted function of WeekdayName(), in the following terms:
You provide a week day name (e.g. Sunday)
You get the correspondent week day number (that depends which is the first week day as returned in WeekdayName, e.g., you get 1 for Sunday if Sunday is the first day of the week)
Background:
I'm using date functions in vb.net. So far so good. I'm using the function WeekdayName() in order to set the titles for tab pages in a TabControl. My custom control (kind of calendar control) holds the mentioned TabControl and it has the option of choosing which day of the week you want to diplay.
If you want to display ALL days, the TabControl will have TabPages filled by iterating upon the WeekdayName() function mentioned above (localized and managed by the system calendar and capitalized by me).
If you set only Tuesday and Friday, you will have two tab pages with those titles and sorted as [Tuesday | Friday]. If you decide to add Wednesday, now you should have 3 tab pages: [Tuesday | Wednesday | Friday], and so on...
In order to keep tabs sorted, when I need to insert a tab to be shown I want to provide the tab's title to check against the new-to-insert weekday name and in that way have the order resolved.
I believe one workaround is to create a fake date object with the tab's title string in it in order to have a, for instance, "Sunday" date and then use: Weekday() but I was hoping an API solution.
NOTE: This is not: how to get the day number from a date.
EDIT:
As we disscused with #jmshapland, a custom code approach using the default localization and system settings could be:
Function WeekdayNumber(day as String)
' The following initialization does not necessary go in this function.
' The idea is to have a mapping between key day name and index in the
' same order as the WeekdayName() method with the default system settings
Dim weekdayNamesCollection as Collection = New Collection()
For i = 1 to WEEKDAYS
Dim wDay as String = WeekdayName(i)
' add the day with a key with the same name
weekdayNamesCollection.add(wDay, wDay)
Next i
If weekdayNamesCollection.ContainsKey(day) Then
Return weekdayNamesCollection.IndexOfKey(day) + 1
End If
' Raise an error as the string 'day' is not in the collection
End Sub
I didn't test this out as I am in a computer without any framework and/or IDE. But basically, the idea is to return the index where the weekday name is stored in the collection (previously, it was stored in the system settings order as WeekdayName().
I don't think there's a built-in function for it. But if you are using WeekdayName then you should use it for your purpose.
Public Function WeekDayNumber(ByVal weekName As String) As Integer
Dim weekNames As New Dictionary(Of String, Integer)
For i As Integer = 1 To 7
weekNames.Add(WeekdayName(i), i)
Next
Return weekNames(weekName)
End Function
Sorry if this is formatted poorly, I never work with VB usually just C#. However, this should do what you are looking for... If you want the first day of the week to return as 0 instead of 1 just remove the + 1 from the return statement.
Private Function FindDayOfWeek(day As String) As Integer
Dim daysOfWeek = CultureInfo.CurrentCulture.DateTimeFormat.DayNames
Dim counter As Integer = Array.IndexOf(daysOfWeek, WeekdayName(1))
Dim numericDay As Integer
For i As Integer = 0 To 6
If counter > 6 Then
counter = 0
End If
If daysOfWeek(counter) = day Then
numericDay = i
Exit For
End If
counter += 1
Next
Return numericDay + 1
End Function
By using val() function, will give Day of Week number from 0 to 6 :
intDayofWeek = val(System.DateTime.Now.DayOfWeek)
I wanna have a drop down that lets me select "Week Commencing Monday the 20th" going back 10 Mondays but I'm not sure how to go about doing this.
I've used date.now(), etc. before but not sure how to do this one.
Thanks,
Billy
UPDATED CODE
Public Sub GetMondays()
Dim dtMondays As New DataTable()
dtMondays.Columns.Add("Date")
Dim i As Integer = 1
While (dtMondays.Rows.Count < 11)
Dim Day As DateTime = Today.AddDays(-i)
If Day.DayOfWeek = 1 Then
dtMondays.Rows.Add(Day)
End If
i += 1
End While
drpDate.DataSource = dtMondays
drpDate.DataBind()
End Sub
You could come up with a formula for calculating the dates of the previous Mondays, but why not do something simple:
Begin loop.
Subtract one day.
Check if it is Monday.
If so, add to a list.
If the list contains 10 elements, exit loop.
Go back to start of loop.
I'm sure you can implement that. It's not that fastest way, but it's simple and probably fast enough for most purposes. If you want to optimize it, you can do so, but it's probably not worth your time unless this is being executed many times per second.
Let's work through it. I'll do this in C# but hopefully some enterprising young polyglot can do the translation for me and score the accepted answer.
DateTime.Today gets you today's date. DateTime.Today.DayOfWeek gets you today's "day of the week" as an enum, where Sunday is 0 and Saturday is 6.
So we can get the latest Monday using:
var lastMonday = DateTime.Today.AddDays(1 - (int)DateTime.Today.DayOfWeek);
edit There's one little glitch here, in that if today is Sunday you'll be getting tomorrow's date, not last Monday's. There's probably some really tricky mathematical way to get around that, but it's just as easy to throw in an extra check:
if (lastMonday > DateTime.Today) lastMonday = lastMonday.AddDays(-7);
Then we just need to get ten of them:
var lastTenMondays = from i in Enumerable.Range(0, 10)
select lastMonday.AddDays(i * -7);
I was searching for something similar, only that I wanted to display the upcoming Mondays. This thread helped in some way. Thanks!
Even though this thread is old, for any one coming across, this may be helpful:
Public Sub Form5_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim nextMondays = DateTime.Today.AddDays(1 - CInt(DateTime.Today.DayOfWeek))
Dim i As Integer = 1
If nextMondays < DateTime.Today Then
nextMondays = nextMondays.AddDays(+7)
End If
For i = 0 To 14
ComboBox1.Items.Add("Mon. " + nextMondays.AddDays(i * +7))
Next i
End Sub
It's probably late but might be helpful for others.
You can do what Mark said but instead of continuing the loop once you find a Monday you can then subtract 7 (or add if you want to find the next 10 mondays) days and get the other monday and you can do this 10 times
* Begin loop.
* Subtract one day.
* Check if it is Monday.
o If so, add to a list.
o (in a for i = 1 to 10 loop) add 7 days and add to list (end for loop)
* Go back to start of loop.
this might save up some time.