Python Datetime string parsing: How to know what has been parsed? - python-datetime

I want to use Python to parse a user input string and need to know which portion of date has been specified, e.g.,
"Jan. 2017" => Month = 1, Year = 2017
The result should tell me only month and year are specified in the string, and return those values, while:
"2003-05-01"
specifies day, month and year.
I tried to use dateutil.parser.parse, and gave it a rare default date value. e.g., 1900/01/01, and then compare the parsed result with the default date and see the difference. But if the month or day are both 1 in the parsed result,
it needs one more round of parsing with a different default value, in order to rule out the possibility of it being the default value, or from the user input.
The above way seems quirky. Is there a library for me to parse commonly used date string format and knowing what has been parsed?

I ended up doing the quirky way:
from dateutil.parser import parse
# parse the date str, and return day/month/year specified in the string.
# the value is None if the string does not have information
def parse_date(date_str):
# choose two different dates and see if two parsed results
default_date1 = datetime.datetime(1900, 1, 1, 0, 0)
default_date2 = datetime.datetime(1901, 12, 12, 0, 0)
year = None
month = None
day = None
try:
parsed_result1 = parse(date_str, default=default_date1)
parsed_result2 = parse(date_str, default=default_date2)
if parsed_result1.year == parsed_result2.year: year = parsed_result2.year
if parsed_result1.month == parsed_result2.month: month = parsed_result2.month
if parsed_result1.day == parsed_result2.day: day = parsed_result2.day
return year, month, day
except ValueError:
return None, None, None

Related

how to extract the today's date out of the date column using SQL query?

I assume I would need to change query in order to sort the data with today's date.
Please tell me how to change it though...
SQL QUERY in ToDoDao
#Query("SELECT * FROM todo_table WHERE date(date) = date('now')")
fun getTodayList(): Flow<List<ToDoTask>>
DATABASE
#Entity(tableName = DATABASE_TABLE)
data class ToDoTask(
#PrimaryKey(autoGenerate = true) val id: Int = 0,
#ColumnInfo(name = "title") val title: String,
#ColumnInfo(name = "description") val description: String,
#ColumnInfo(name = "priority") val priority: Priority,
#ColumnInfo(name = "date") val date: String,
#ColumnInfo(name = "favorite") var favorite: Boolean)
date val in ViewModel class
val date : MutableState<String> = mutableStateOf("")
datas inserted
enter image description here
I have tried the code below and I was able to activate the function as the query as I intented, so I think the query is the issue here.
#Query("SELECT * FROM todo_table WHERE date = '2023-2-14'")
fun getTodayList(): Flow<List<ToDoTask>>
The Issue
The issue is that the SQLite date function expects the date to be in an accepted format.
YYYY-M-DD is not such a format and will result in null rather than a date. YYYY-MM-DD is an accepted format (see https://www.sqlite.org/lang_datefunc.html#time_values). That is leading zeros are used to expand single digit numbers to 2 digit numbers for the month and day of month values.
The Fix (not recommended)
To fix the issue you have shown, you could use (see the However below):-
#Query("SELECT * FROM todo_table WHERE date(substr(date,1,5)||CASE WHEN substr(date,7,1) = '-' THEN '0' ELSE '' END ||substr(date,6)) = date('now');")
If the month was 2 numerics i.e. MM (e.g. 02 for February) then the above would not be necessary.
The CASE WHEN THEN ELSE END construct is similar to IF THEN ELSE END. see https://www.sqlite.org/lang_expr.html#the_case_expression. This is used to add the additional leading 0, when omitted, to the string used by the date function.
However, the above would not cater for days that have the leading 0 omitted for the first 9 days of the month. This due to the 4 permutations of the format (YYYY-MM-DD, YYYY-MM-D, YYYY-M-D and YYYY-M-DD) would be more complex e.g.
#Query("SELECT * FROM todo_table WHERE date(CASE WHEN length(date) = 8 THEN substr(date,1,5)||'0'||substr(date,6,1)||'-0'||substr(date,8) WHEN length(date) = 9 AND substr(date,7,1) = '-' THEN substr(date,1,5)||'0'||substr(date,6) WHEN length(date) = 9 AND substr(date,8,1) = '-' THEN substr(date,1,8)||'0'||substr(date,9) ELSE date END) = date('now');")
Recommended Fix
The recommended fix is to store values using one of the accepted formats rather than try to manipulate values to be an accepted date to then be worked upon using the date and time functions.

Carbon setTestNow function is not working

I am working on dates in Laravel. I have to set dates for patient future injections.
To keep it simple, let's suppose today is 13-03-2019 (Wednesday).
I created first date as:
$firstDate = Carbon::create(2019,03 ,18, 12); // The day is Monday
// set date
Carbon::setTestNow($firstDate);
Now I want the next two appointments should be on Wednesday and Friday. So I again set the dates as follow:
// set second date
$secondDate = new Carbon('Wednesday');
Carbon::setTestNow($secondDate);
// set thirdDate
$thirdDate = new Carbon('Friday');
Carbon::setTestNow($thirdDate);
According to above example the output should be:
2019-03-18
2019-03-20
2019-03-22
But the problem is that it outputs the first set date correct but print the 2nd and 3rd date wrong as it considers 'Wednesday' of next week as today's date.
So the Output print as:
2019-03-18
2019-03-13
2019-03-14
I have spent a lot of time on it, I would appreciate if anyone of you people could help me in this.
I would appreciate if anyone guides me where I am going wrong.
Thanks.
As the setTestNow() function was not working for 2nd and third date/days, so I first get all three required days then convert them to 'dayOfWeek' which returns day number (Sunday 0, Monday 1 and so on...). I subtracted the first day from second and third day and then finally add these days to the date that i get from the datepicker.
// set the start date
if( $visitstart_date != null && $visitstart_date != '') {
Carbon::setTestNow($visitstart_date);
} else {
Carbon::setTestNow();
}
if($perweek_visit1_day != '')
{
//Get first selected day number
$firstDay = Carbon::parse($perweek_visit1_day)->dayOfWeek;
$perweek_visit1_dayDate = Carbon::now();
}
if($perweek_visit2_day != '')
{
//Get second day numer
$secondDay = Carbon::parse($perweek_visit2_day)->dayOfWeek - $firstDay;
$perweek_visit2_dayDate = Carbon::now()->addDays($secondDay);
}
if($perweek_visit3_day != '')
{
//Get third day number
$thirdDay = Carbon::parse($perweek_visit3_day)->dayOfWeek - $firstDay;
$perweek_visit3_dayDate = Carbon::now()->addDays($thirdDay);
}

VB6 week of day function

I'm relatively new to VB6 and I've just been given an assignment where I have a date - for example '4/12/2016' - from this date, i'm trying to find out the day that it is. So let's say it's a wednesday. Now from this day, I'm trying to determine the dates for the week [sun(startdate) - sat(enddate)). How would I go about doing something like this?
EDIT: I have a pretty good idea about finding out the date for sunday and saturday, since I can simply do something along the lines...
dim dateStart,dateend as date
Ex of date given to me = '4/12/2016'
Dim dateDay as variant
dateDay = whatever I get here - i'm assuming that a date will return a number for whatever day it is ???? Not sure
Select Case dateDay
case 1 -Monday?
dateStart=dateadd("d",-1,'4/12/2016)
dateEnd = dateadd("d",6, '4/12/2016)
case 2 -Tuesday?
datestart = dateadd("d",-2,'4/12/2016)
dateend = dateadd("d",5,'4/12/2016)
End Select
Basically do the SELECT statement for all cases. Am I on the right track?
This code:
Debug.Print Format(DatePart("w", Now), "dddd")
will print whatever day of the week it is now to the Immediate window. If you want the abbreviated day of week, use "ddd" for the format.
Now, this code:
Dim DOW As String
Select Case DatePart("w", Now)
Case vbSunday
DOW = "Sunday"
Case vbMonday
DOW = "Monday"
Case vbTuesday
DOW = "Tuesday"
Case vbWednesday
DOW = "Wednesday"
Case vbThursday
DOW = "Thursday"
Case vbFriday
DOW = "Friday"
Case vbSaturday
DOW = "Saturday"
End Select
Debug.Print DOW
will do the same thing. However, it shows you how to evaluate programmatically which day of the week you're dealing with, by using vbSunday, vbMonday, etc. That should give you what you need to get started on your Select statement. To use your example, DatePart("w", "4/12/2016") evaluates to 3, or vbTuesday.
VB6 reference documentation is here, and rather well hidden I might add. Look up Format and DatePart to get familiar with other options.
EDIT: As MarkL points out, the Weekday function is available in VB6 (I thought it wasn't), and is simpler (one less argument) than using DatePart. This code:
Debug.Print Format(Weekday(Now), "dddd")
will also print whatever day of the week it is to the immediate window. jac has also provided a link to the Weekday function in the comments above.
You can try below codes, The code will return name of the day.
txtDateTime.Text = WeekdayName(Weekday(Now))
txtDateTime.Text = WeekdayName(Weekday(12 / 30 / 1995))
txtDateTime.Text = WeekdayName(Weekday(Date))

How to check if event's date is within a date range?

I have events (from an Event model) that have a starts_at: value in the form of a datetime. e.g.:
2016-02-18 11:00:00:00000
What I want to be able to do is check whether an event is starting this week.
I want to be able to make a list of events that are occuring this week (starting from the latest Monday).
#events = #calendar.events.where( ... )
I thought something along the lines of this:
start_week = Date.today.beginning_of_week(:monday).day()
end_week = Date.today.beginning_of_week(:monday).day()+6
range = start_week..end_week
#events = #calendar.events.where(starts_at: in range)
But it doesn't take into account the month or year. Also I'm not sure how to write the 'where' clause. How should I go about doing this? Thanks
Try this:
start_week = Date.today.beginning_of_week(:monday)
end_week = Date.today.beginning_of_week(:monday)+6
range = start_week..end_week
#events = #calendar.events.where(starts_at: range)
Assuming you want all the events from the current week, something like this should work:
#events = #calendar.events.where(starts_at: Time.zone.today.all_week)
all_week returns a Date range covering the current week.

Date Validation: Setting minimum and maximum date in a Textbox

I have a function in my VBA code which sets a specific Date format for a textbox.
This is my code to verify the Date is in the correct format:
Function CheckDate(DateStg As String) As Boolean
If DateStg = "" Then
' Accept an empty value in case user has accidentally moved to a new row
CheckDate = True
lblMessage.Caption = ""
Exit Function
End If
If IsDate(DateStg) Then
CheckDate = True
lblMessage.Caption = ""
Else
CheckDate = False
lblMessage.Caption = "Sorry I am unable to recognise " & DateStg & " as a date."
End If
End Function
In addition to checking if the date in the textbox is an actual date, I need to verify that the textbox date is not less than the current date minus 1 month, and. Also, I would like to verify that the date is not more than the current date plus 1 year.
So:
DateStg > Today - 1 month
DateStg < Today + 1 year
Thanks for your help in advance.
You have a few functions you can use:
''Assume date is not good
DateOK=False
If IsDate(DateStg) Then
If DateStg > dateAdd("m",-1,Date()) _
And DateStg < dateAdd("m",12,Date()) Then
''Date is good
DateOK=True
End If
End if
For the most part, textboxes can be set to only accept dates and you can set validation rules to check the range, so code may not be necessary.
If you just want to check the date, you can use the DateAdd-function to get the dates to compare:
'Subtract a month from today and return it as a string
Format(DateAdd("m", -1, Now), "yyyy-mm-dd")
'Add a year to today and return it as a string
Format(DateAdd("yyyy", 1, Now), "yyyy-mm-dd")

Resources