Informix-SE 4.10 with isql 4.10 DD6:
I have a DATE column, BirthDate, linked to a perform field tag "dob". When users enter the dob, I am doing the following date arithmetic:
age = (TODAY - dob ) / 365.25
field tag age is DISPLAYONLY TYPE DECIMAL field, with FORMAT="##.##".
This method is not producing accurate results.
Business Rule: Example, If a person true age is not 18 years old the day before their 18th birthday, I need to display 17 in the age field tag, and abort insertion of the customer row. Person must be >=18 years old.
DATETIME and INTERVAL datatypes are supported in this ifx version, but users are only comfortable entering dates in MMDDYYYY format.
In order to determine if the birthday has happened this year, you must be sure not to generate a non-valid date in the case where dob is February 29 and TODAY is in a non leap-year. Since 2000 is a leap-year, you can avoid the problem making the subtraction always for the year 2000.
MDY(MONTH(dob), DAY(dob), 2000) > MDY(MONTH(TODAY), DAY(TODAY), 2000)
Finally, subtract one from the year difference if so:
age = (YEAR(TODAY) - YEAR(dob) -
CASE WHEN MDY(MONTH(dob), DAY(dob), 2000) > MDY(MONTH(TODAY), DAY(TODAY), 2000)
THEN 1 ELSE 0 END)::int
Related
I have created a parameter in Tableau called Fiscal Start Month and it represents an integer for the beginning month of my fiscal year which is May. The integer is set to -8. I created this calculation to show the dates in the relative time frame which should be May 1 - December 31, 2022. The "DOS" is a date field for Date of Service, and I created another calculated field called "date" for today's date:
IF [DOS] >=DATE(DATEADD('month',[Fiscal Year Start],[Date])) AND [DOS] <=DATE(DATEADD('month',1,DATETRUNC('month',[Date])))
THEN 'Show'
ELSE 'Hide'
END
When I filter my data I am getting items from May 5th and it is hiding May 1 - 4. Can someone help me understand why this calculation might not bring in the appropriate dates?
I tried the formula above and this is what I am expecting
enter image description here
I have a Date variable with a person's date birthday. I would like to know how many days remains before this person next birthday. It should be calculated from today date to current year birthday date.
How can this be done with Swift? Also it will be great to consider February 29 in leap years.
To the guys who tried to close this: This is about birthday which has totally different rules from days.
Birthdays are complicated. Your birthday was the date of the moment when you were born, in the timezone where you were born. Considering that Samoa = UTC+14 and Baker Island = UTC-12, it is possible that people born at the same moment in time have birthdays that are two days apart.
So to store somebody's birthday, not the moment of birth, you either store year/month/day, or if you want to store it as a point in time, you store the beginning of that day in UTC, with the understanding that this is to specify a day, and must not be converted to local time.
Now when does your birthday repeat? If the person is born on D/M/Y and D/M is not February 29th, then the next birthday is either D/M/current year or D/M/next year. It is D/M/current year if that date is in the future, otherwise D/M/next year.
If the person is born on February 29th, then you have to determine when officially the next birthday is if the year is not a leap year - this will be February 28th or March 1st, depending on which rules apply.
We also need to clarify what "number of days" means. If my birthday is on April 1st, and now it is March 31st, one second to midnight, my birthday will be one second from now. However, I will assume that the result is supposed to be "one day from now".
So here is the algorithm:
Step 1: Find day/month/year when the person was born.
Step 2: Determine the current time, and convert it to local day/month/year. Determine the current time only once to avoid problems if this calculation is done nanoseconds before midnight.
Step 3: Determine the year when the birthday repeats: If day/month of birthday is greater than current day/month, then the year when the birthday repeats is the current year, otherwise the next year. This is also correct if the birthday was on Feb. 29th.
Step 4: Determine the day/month when the birthday repeats: This is the same as the day/month of the birthday, unless the birthday was on Feb. 29th and the year when the birthday repeats is not a leap year. In that case, the birthday repeats on Feb 28th or March 1st, depending on which rules you decide to apply.
Step 5: Convert the current day/month/year + 12 hours to UTC. Convert the date when the birthday repeats + 12 hours to UTC. Calculate the difference in seconds (which the OS should do for you). Divide by 86,400, then round to the nearest integer. The "+12 hours" and "round to nearest integer" make sure that you have no problems with daylight savings time, leap seconds etc.
Writing this code in Swift or any other language should be no problem.
It depends on what you are looking to use the days value for but here is a small function that will return a Double describing the amount of days until a given Date. Martin R gave a really good answer here and my answer is mainly based on theirs with a little bit of documentation added.
/// This function takes a `Date` parameter and returns an `Int` describing how many days away the `Date` is into the future (accounting for leap years by making 2/29 dates land on 3/1 in non-leap years).
/// - Parameter date: The `Date` object to be evaluated.
func daysUntil(birthday: Date) -> Int {
let cal = Calendar.current
let today = cal.startOfDay(for: Date())
let date = cal.startOfDay(for: birthday)
let components = cal.dateComponents([.day, .month], from: date)
let nextDate = cal.nextDate(after: today, matching: components, matchingPolicy: .nextTimePreservingSmallerComponents)
return cal.dateComponents([.day], from: today, to: nextDate ?? today).day ?? 0
}
I have nodes with person label where i am storing their date of births too. For e.g.:
Person
{
name: Tim
D.O.B: 01/23/1990
}
Now I need to calculate his age as of current date and time ( i.e. either 27 years or 27 years, 10 months, 18 days ). So, could anyone let me know how could I perform it?
P.S.: I tried the following but seems to be missing something here :
WITH apoc.date.parse('01/23/1990', 'y', 'MM/dd/yyyy') AS startDate,
apoc.date.format(timestamp(),'y','MM/dd/yyyy') as endDate,
apoc.date.parse(endDate,'y','MM/dd/yyyy') as ed
RETURN ed - 4
The units supported by the APOC date format/parse/add/convert functions are: ms,s,m,h,d and their long forms. To work with months, you need to be working with a specific calendar system, and there is no common month unit of time to do conversions or additions, as different months are comprised of different days (then there's the leap days in February).
For years, you're going to have to go with day units and use division by 365.
Here's a query that will get you age in years and days.
WITH apoc.date.parse('01/23/1990', 'd', 'MM/DD/yyyy') as birth, apoc.date.convert(timestamp(), 'ms', 'd') as now
WITH now - birth as daysAlive
RETURN daysAlive / 365 as yearsAlive, daysAlive % 365 as daysExtra
If you want to get into months, it may be better to work with the month/year fields from the MM/DD/yyyy representation and pull some mathematics on those. I'll see about what we can for supporting that in APOC.
Some like
WITH apoc.date.parse('01/23/1990', 'y', 'MM/dd/yyyy') AS startDate
RETURN apoc.date.convert(timestamp() - startDate,"ms","d");
perhaps ?
Hope this helps.
Regards,
Tom
Informix is not my normal environment and the way it handles datetime values is throwing me for a loop. I can't imagine this is difficult, but for the life of me I'm not yet able to figure it out.
This is the SQL:
SELECT agentid,
extension As Ext,
resourcefirstname As FirstNm,
resourcelastname As LastNm,
Min(eventdatetime) As FirstIn
FROM agentstatedetail AS asdr Join
resource As r On asdr.agentid = r.resourceid
WHERE asdr.eventdatetime BETWEEN '2016-10-20 04:00:00' AND '2016-10-21 03:59:59'
AND eventtype = 3
AND assignedteamid = 14
Group By agentid, extension, resourcefirstname, resourcelastname
Order By Min(eventdatetime)
Everything works as is, but the dates in the Between clause are currently entered manually- not optimal. I just need some way to describe "yesterday at 4:00 AM" and "Today at 4:00 AM" Will somebody please clue me in?
Using Informix version 12.10.FC6DE, I can do this:
SELECT
TODAY::DATETIME YEAR TO SECOND AS today_zerohour
, TODAY::DATETIME YEAR TO SECOND - '20:00:00'::INTERVAL HOUR TO SECOND AS yesterday_dawn
, TODAY::DATETIME YEAR TO SECOND + '04:00:00'::INTERVAL HOUR TO SECOND AS today_dawn
FROM
systables
WHERE
tabid = 1;
And it returns:
today_zerohour yesterday_dawn today_dawn
2016-10-21 00:00:00 2016-10-20 04:00:00 2016-10-21 04:00:00
So, what is happening here:
The operator TODAY returns the system date as a DATE type. The DATE type does not have the precision I want (it only has year, month and day), so I cast the value (cast operator is ::) to a DATETIME with precision from year to second (the hour, minutes and seconds are set to zero):
TODAY::DATETIME YEAR TO SECOND
In Informix, for an addition or subtraction with a DATETIME value to return another DATETIME value, I need to add or subtract an INTERVAL value. So I created 2 INTERVAL values.
One INTERVAL of 20 hours to subtract from the today value (again the cast operator :: is used, this time to cast from a string to an INTERVAL):
'20:00:00'::INTERVAL HOUR TO SECOND
One INTERVAL of 4 hours to add to the today value:
'04:00:00'::INTERVAL HOUR TO SECOND
I want to store date in my Postgres database.
The only problem is that this date can have optional day or even month.
Example:
User provides time period when he was employed - not necessary full date (day + month + year), but only start year and end year.
However there are users, who worked only from may to october in the same year so month have to be provided too.
How to handle this kind of optional date parts?
Use a proper date type anyway. Do not store text or multiple columns. That would be more expensive and less reliable.
Use the function to_date(), which is fit to deal with your requirements out of the box. For instance, if you call it with a pattern 'YYYYMMDD' and the actual string is missing characters for day, or month and day, it defaults to the first month / day of the year / month:
db=# SELECT to_date('2001', 'YYYYMMDD');
to_date
------------
2001-01-01
db=# SELECT to_date('200103', 'YYYYMMDD');
to_date
------------
2001-03-01
You could store a precision flag indicating year / month / day in addition if you need that.
While the accepted answer is a good one, there is another alternative.
ISO 8601
The ISO 8601 standard defines sensible formats for textual representations of various kinds of date-time values.
A year is represented in the obvious manner, a four-digit number: 2014
A year-month is represented with a required hyphen: 2014-01Note that in other ISO 8601 formats, the hyphen is optional. But not for year month, to avoid ambiguity.
A full date is similar: 2014-08-21 or without optional hyphens: 20140821. I recommend keeping the hyphens.
So you could store the values as text. The length of text would tell you whether it is year-only, year-month, or date.