How to get a valid Date as input from GUI - datetime

I have a school practical where users enter their date of birth in a TEdit on a TForm. The user will most likely enter the date according to their custom date settings, but I want to be able to convert any or at least most date formats to the one I have stored in a .mdb Access database. How do I get an accurate and valid date from the GUI as user input?
I know of the decodedate(Date, year, month, day) procedure, but what if the user enters the date differently than system settings or as is displayed in the TDBGrid connected to the .mdb database via an ADOConnection and ADOTable? Then the procedure will crash.

Be a help to the user instead of a pain:
Is "contains" meant literally, so the user can actually also enter dates with leading and/or trailing spaces? Such things occur, especially when copying texts from elsewhere. Trimming off such whitespaces is easy, so allow this. See trim()
Avoid generic error messages but instead make them as precise as possible:
Wrong length? Tell what you expect and what you got instead, i.e.: "Expected length: 10, but got 8 instead."
No delimiter at expected position? Tell so, i.e.: "Expected delimiter "/" as 5th letter, but got "3" instead."
Illegal month? Tell so, i.e: "Expected "1" or "01" thru "12" as month, but got "23" instead."
Try to collect multiple error messages at once, so the user can see all of his mistakes and fix them in one go, instead of being penalized again and again with just one message per take.
Detect patterns and make them restrictive:
Pos #1 is in ['0'.. '2'] and pos #2 thru #4 is in ['0'.. '9']? Looks like a year from which we can proceed:
Pos #5 is in ['/', '-', '.']?
Pos #6 is '0' and pos #7 is in ['1'.. '9']? Or pos #6 is '1' and pos #7 is in ['0'.. '2']?
...and so on. That way you can much better recognize which format has been chosen and you can give much more precise error messages. It will also lead to ambiguous input, such as 4/10/2016 from which you don't know if 4 is a day or a month.
Check against illegal dates: which months cannot have a 31th day? For February 29th see IsLeapYear()
Display the date according to what you recognized - this helps you and your user to make sure the recognition was correct. Ideally you have your three Integers of year, month and date and then convert them to text again, along with delimiters - the outcome should be in general the input you had to deal with.
Regular expressions are great in recognizing patterns and then accessing the found parts. However, it's a topic on its own and should only be used when known on its own. A regex for the format I used in this example would be /([0-2][0-9]{3})[/.-](0?[1-9]|1[0-2])[/.-](0?[1-9]|[12][0-9]|3[01])/ where you can easily access $1 as year, $2 as one or two digit month and $3 as one or two digit day. You "only" have to check against illegal dates.

As #AndreasReijbrand pointed out, a TDateTimePicker would be the correct method to receive a date as user input on a GUI. The TDateTimePicker does all the validation work for you. After much debate, we were eventually allowed to use it. I post this new answer with some important insights to the TDateTimePicker component:
The TDateTimePicker automatically changes to the local set date format of the pc. So validation of that is unnecessary.
Conversion of date display format (yyyy/mm/dd or yyyy-mm-dd) from the .mdb Access database to the TDateTimePicker and vice versa is unnecessary. This is also done automatically. (Starting to see why there was so much criticism for the original lack of use of this component.)
The DateTimePicker does not allow negative values or non-sensical values such as (0030/09/08 or 2003/89/89).

Related

Preventing magic numbers used in firebase realtime database

So I want to specify a time after which a post gets deleted. The time is 3 months, in my code I would define this as
const THREE_MONTHS_IN_MS = 7889400000
export const TIME_AFTER_WHICH_USER_IS_DELETED = THREE_MONTHS_IN_MS
How can I define this in my database without resorting to the use of a magic number? Basically it looks like this right now:
timeAfterWhichUserIsDeleted: 7889400000
Or as a direct screenshot of the database: https://gyazo.com/67abfdc329e1e36aae4e66b0da4b4f75
I would like to avoid this value in the database and instead have it be more readable.
Any tips or suggestions?
The 7889400000 is a UNIX timestamp, indicating a number of milliseconds since the epic. While you can store a value indicating the same moment in a different format, you'll want to make sure that the format you use still allows you to query the value.
A common format that is both readable and queryable it ISO-8859-1, and my current time in that format would be 2022-03-22 06:50:48.
I noticed after re-reading your question that your timeAfterWhichUserIsDeleted is actually an interval and not a moment. If the interval is always going to be in months, you could store countOfMonthsAfterWhichUserIsDeleted: 3 as a more readable form of the same intent. Just note that 3 is equally magic as 7889400000 and the main difference is that I've named the field more meaningfully.

Watson Conversation System date entity dateformat changes for '/' vs '-'

Watson Conversation System Entity sys-date is giving different results if I change '/' with '-'
As per documentation:
Note: - For English locale only, the default system behavior for date
input is MM/DD/YYYY. This will change to DD/MM/YYYY only if the first
two numbers are greater than 12. The value stored will still be in the
format "yyyy-MM-dd".
However when i am testing with '-' its taking DD/MM/YYYY
12/01/2017 => 2017-12-01 (Correct)
12-01-2017 => 2017-01-12 (incorrect)
Ideally Watson should interpret both as same dates as this '/', '-' will confuse the users. Is there anyway to make it interpret as same dates.
Date Sample Screenshot
AFAIK it is not possible to change the way the dates are interpreted in the shared version of IBM Watson Conversation Service (WCS). The date which you labeled as incorrect is actually correct when looking at ISO date formats.
What you could do for your customization issue is to assess the metadata provided by WCS. You have access to the location information about where in a string the data was detected and also what exactly the user typed. You could use that to interpret date values in the desired form.

AppInventor: how to insert DateTime into Google Spreadsheet and show only recent DateTime

I am new to this forum so I hope I asking my question in the right place.
I have a problem inserting a datetime into a Google Spreadsheet from a form created in Appinventor2;
In app inventor2 I created a form that fills in a google spreadsheet. Basically I merged the Pizza Party example (http://appinventor.mit.edu/explore/ai2/pizzaparty.html) with this example http://puravidaapps.com/spreadsheet.php to use google spreadsheet instead of fusion table.
the user selects in how many minutes he wants his order and then sees all the orders in a table sorted by delivery time.
Problem A)
Firstly, i want to save the current datetime + the desired delay into the google spreadsheet and sort the table by this new datetime.
1) when i use the block "call clock format time" + "call clock addminutes" the spreadsheet is populated with a text, but then i can't sort the table by delivery datetime. in fact i believe the sorting is done on the number regardless of the am/pm or day of the month. so for example instead of having 4am, 6am, 2pm, 3pm i get : 2pm, 3pm, 4am, 6am.
2) I then tried to remove the block "call clock format time" and in the google form i kept the field format = text
but the google spreadsheet is populated with the following:
java.util.GregorianCalendar[time=1395531335908,areFieldsSet=true,lenient=true,zone=Europe/Dublin,firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2014,MONTH=2,WEEK_OF_YEAR=12,WEEK_OF_MONTH=4,DAY_OF_MONTH=22,DAY_OF_YEAR=81,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=4,AM_PM=1,HOUR=11,HOUR_OF_DAY=23,MINUTE=35,SECOND=35,MILLISECOND=908,ZONE_OFFSET=0,DST_OFFSET=0]
3) I then tried to remove the block "call clock format time" and in the google form I changed the field format = time
but then the google spreadsheet isn't populated with anything.
4)I tried using the segment block, but after a while I realised the block "format time" actually returns this format: "hh:mm:ss AM/PM"
so selecting the 5 characters is not good enough because it does not take into account of the am/pm element as well as the day of the month.
5) I found a temp solution by defining the desired delivery time as a new global variable, and extracting a string in the format hh:mm by joining the blocks ".hour instant" and ".minute instant".
However this is not a final solution because what i extracted is of course a string of text and when sorting, 01:10 will be always considered smaller than 23:50 for example, regardless of the date.
So is there a way of actually saving in the google spreadsheet not a string of text, but actually the date and time?
Problem B)
Secondly, I would like to filter/show only the rows of the google spreadsheet have a delivery time expired by no more than 1 hour (as well as orders with delivery time in the future e.g. in 2 hours from now()).
I tried using some Google Visualization API Query Language commands, altering the url of the google spreadsheet (like WHERE "now() - Delivery Time < 60 mins)" (cannot remember the exact code I wrote) but unsucessfully.
Would anyone know how to filter my results?
thanks in advance
alterettore
So there's a few things to note.
If you're using Taifun's example as you mention, you'll notice that when you submit data to Google Spreadsheets using a form, the first column is always a timestamp, even if you're not submitting a date or time. Trying to send the current date/time is redundant - go ahead and make use of what Google provided.
Google Spreadsheets (and Excel) store Date/Time as a number. If you want to store a date in GS, the best way to do so is not formatted text, but by sending a number. Use AppInventor to calculate the number you need. For example, today (April 27) in GS is 41756. Noon today would be 41756.5
To generate this number, start with AI's Millisecond function. NOTE: Both GS and AI use milliseconds, but they have different 0 points, so you have to manipulate the result a bit. The formula I've used in AI in the past is this:
GS Date/Time = (Clock1.GetMillis(Clock1.Now) / 86400000) + 25569
Hope this helps!

Access 2010 Query with Parameter and Sort

I have a problem that I've been going round and round with in Access 2010. Imagine a table with these columns:
Name Date Time
Now, I have a query that asks the user to input a begin date and an end date and returns all records that are between those two dates. This works fine. However, as soon as I add a sort to the Date column things go awry. Once you put a sort on a column with a parameter the user gets asked to enter the parameter twice. From what I've been able to find out this is normal (although annoying) behavior in Access.
If I add the Date column in a second time and show the column with the sort and don't show the column with the parameter it works fine. The query would look something like:
Name Date (shown & sorted) Date (not shown & parameters) Time
Now when I run the query it all works well and comes out the way I want it to. This would obviously be a great solution then. However, there's another problem. When I save the query, leave, and reopen the query the two columns are merged back into each other. Thus, the change is lost and the user again sees two inputs.
My question is this: what can I do differently to achieve the desired results?
Some possible things I've thought about but don't know the answer to are:
Is there a way to make it so the columns don't merge? Do I have to use a form with the input boxes and take the data from that (I'd prefer not to do that as it will require a lot of additional work to handle the various things I am doing in the database). Is there some obvious thing I'm missing?
Thanks for any suggestions.
FYI: Here is the SQL from the query
SELECT Intentions.Intention, Intentions.MassDate, Intentions.[Time Requested], Intentions.[Place Requested], Intentions.[Offered By], Intentions.Completed
FROM Intentions
WHERE (((Intentions.MassDate) Between [Enter start date] And [Enter end date]))
ORDER BY Intentions.MassDate, Intentions.[Time Requested];
It is true that sometimes the Query Designer in Access will "reorganize" a query when you save it. However, I don't recall an instance where such a reorganization actually broke anything.
For what it's worth, the following query seems to do what you desire. After saving and re-opening it looks and behaves just the same:
For reference, the SQL behind it is
PARAMETERS startDate DateTime, endDate DateTime;
SELECT NameDateTime.Name, NameDateTime.Date, NameDateTime.Time
FROM NameDateTime
WHERE (((NameDateTime.Date) Between [startDate] And [endDate]))
ORDER BY NameDateTime.Date DESC , NameDateTime.Time DESC;
I have had the same problem and I have discovered the reason:
If, after you have run your query, sort a collumn in the result grid and the say yes to save changes to the query the sort action will be stored with the query. This will actually cause the query to run twice. First to create the result and then one more time to sort. You'll therefore be asked twice for the parameters.
SOLUTION: Run the query (entering your parameters twice ;-) ). Then remove the Sorting by clicking on the AZ-eraser symbol in the task bar above (in the sorting compartment).
Then open your query in design-mode and add the sorting order to the appropriate collumn.
Your are then good to go.
Regards
Jan

Reporting Services Sorting by Date issue with TFS Report

Long time reader etc,
I've a TFS report that I want to alter the sorting on by date. The problem is the sort only seems to consider the day element and the rest isn't considered. For example, the following is happening:
1/7/2011
1/7/2011
1/7/2011
2/12/2010
3/03/2011
3/03/2011
I've looked for a way to specify the datatype on the box in the table but to no avail. Any suggestions?
I've realised the field was being treated as text as the date in question isn't guaranteed to be there and replaced with an empty string if it wasn't.
Two steps have fixed the problem:
Added calculated field to dataset and wrapped an iif around to deal with missing dates as being way off in the future.
=CDate(IIf(IsDate(Fields!My_Date.Value), Fields!My_Date.Value, DateAdd(DateInterval.Year, 10,Now)))
This then forces the field to be treated as a date. I then added a sort on the group on this calculated field which isn't shown in the report and gives the impression that those items with a date get ordered and the rest are left to the other layers of sorting which is correct.
Is there a better way of doing this?
I find it a very efficient way!
I did it myself more complex
Group properties of the field you want to sort on
Sorting
expression:
=Datepart("yyyy",Fields!Datum.Value) & Datepart("m",Fields!Datum.Value) & Datepart("d",Fields!Datum.Value)
It will sort first on year, then on month, then on day

Resources