Google Sheets DATEDIF Function showing incorrect days - date

I'm trying to calculate someone's age so that it displays the number of years, months, and days between their birthday and today() using this formula
=DATEDIF(A1,TODAY(),"Y")&" years "&DATEDIF(A1,TODAY(),"YM")&" months "&DATEDIF(A1,TODAY(),"MD")&" days"
I thought it was working fine until I noticed that date at the beginning of a month,
showed the same age as the date at the start of the next month:
It looks to me like Google uses a blanket 30 days when calculating DATEDIF and "MD". Is there a way to fix or work around this?
Here is a link to a test spreadsheet to work with

nice find! I would call it a bug and report the issue to google via:
as this is ridiculous as their faulty documentation!
here is an alternative:
=INDEX(LAMBDA(B, N, IF(ISDATE_STRICT(B), TRIM(FLATTEN(QUERY(TRANSPOSE(
IFERROR(LAMBDA(A, LAMBDA(X, IF(X<=0,,IF(X>1, X&A&"s", X&A)))
({DATEDIF(B, N, "Y")-IF((DAYS(N, B)<365), (IF(DAYS(N, B)<DAY(EOMONTH(N, -1)),
DAYS(N, B), IF(DAY(B)>1, DAY(EOMONTH(B, ))-DAY(B)+1, 0)+DAY(N)-1)>=
DAY(EOMONTH(B, ))))-(((LAMBDA(Q, Q-QUOTIENT(Q, 12)*12)
(COUNTUNIQUE(EOMONTH(SEQUENCE(N-B, 1, B), ))-2+
(DAY(B)=1)+(DAY(N)=DAY(EOMONTH(N, )))))=11)*((IF(DAYS(N, B)<DAY(EOMONTH(N, -1)),
DAYS(N, B), IF(DAY(B)>1, DAY(EOMONTH(B, ))-DAY(B)+1, 0)+DAY(N)-1))>30)),
LAMBDA(Q, Q-QUOTIENT(Q, 12)*12)(COUNTUNIQUE(EOMONTH(SEQUENCE(N-B, 1, B), ))-2+
(DAY(B)=1)+(DAY(N)=DAY(EOMONTH(N, )))), IF(DAYS(N, B)<DAY(EOMONTH(N, -1)),
DAYS(N, B), IF(DAY(B)>1, DAY(EOMONTH(B, ))-DAY(B)+1, 0)+DAY(N)-1)}))
({" year", " month", " day"}))),,9^9))), ))(B1, NOW()))
for array B1:B100 it would be:
=INDEX(BYROW(B1:B100, LAMBDA(B, LAMBDA(B, N,
IF(ISDATE_STRICT(B), TRIM(FLATTEN(QUERY(TRANSPOSE(
IFERROR(LAMBDA(A, LAMBDA(X, IF(X<=0,,IF(X>1, X&A&"s", X&A)))
({DATEDIF(B, N, "Y")-IF((DAYS(N, B)<365), (IF(DAYS(N, B)<DAY(EOMONTH(N, -1)),
DAYS(N, B), IF(DAY(B)>1, DAY(EOMONTH(B, ))-DAY(B)+1, 0)+DAY(N)-1)>=
DAY(EOMONTH(B, ))))-(((LAMBDA(Q, Q-QUOTIENT(Q, 12)*12)
(COUNTUNIQUE(EOMONTH(SEQUENCE(N-B, 1, B), ))-2+
(DAY(B)=1)+(DAY(N)=DAY(EOMONTH(N, )))))=11)*((IF(DAYS(N, B)<DAY(EOMONTH(N, -1)),
DAYS(N, B), IF(DAY(B)>1, DAY(EOMONTH(B, ))-DAY(B)+1, 0)+DAY(N)-1))>30)),
LAMBDA(Q, Q-QUOTIENT(Q, 12)*12)(COUNTUNIQUE(EOMONTH(SEQUENCE(N-B, 1, B), ))-2+
(DAY(B)=1)+(DAY(N)=DAY(EOMONTH(N, )))), IF(DAYS(N, B)<DAY(EOMONTH(N, -1)),
DAYS(N, B), IF(DAY(B)>1, DAY(EOMONTH(B, ))-DAY(B)+1, 0)+DAY(N)-1)}))
({" year", " month", " day"}))),,9^9))), ))(B, NOW()))))
ofc, this will work only up to a particular moment in history...
see: https://stackoverflow.com/a/74006429/5632629
otherwise, this works even with leap years
also, note this feature...
how can be something old 36 days when the smallest unit of the month is 28 days and the largest unit of the month is only 31 days?
as it would not be fair / accurate to transfer Sep days into Dec nor Dec days into Sep to fill out the month as it would create multiple correct results:
3 months 5 days if Sep days transferred to Dec
3 months 6 days if Dec days transferred to Sep

Related

Using Conditionals and Time & Date in Assembly Language

I'm new with assembly language (8086 Program) and I am trying to create a program that display a greeting depending on system date and time. Like if the system date is December 25 then the program will print "Merry Christmas" or if January 1 then it's "Happy New Year". If it just a regular day / no holiday then just print a "Good day". On system time, probably display a "Good Evening" or "Good Morning".
So far, I learned how to get and display the system time and date. Now, I am wondering how can I apply conditionals (if-else) on it.
Assuming you've asked the date from DOS using function 2Bh, the day will be in DL and the month in DH. Checking for Christmas day is simply writing cmp dx, 0C19h.
Get inspired by next example:
mov si, Xmas
cmp dx, 0C19h ; 25 dec
je GoPrint
mov si, NewY
cmp dx, 0101h ; 01 jan
je GoPrint
...
GoPrint:
mov dx, si
mov ah, 09h ; DOS.PrintString
int 21h
...
Xmas: db 'Merry ...', 13, 10, '$'
NewY: db 'Happy ...', 13, 10, '$'
For 'Good day' vs 'Good evening', you can apply similar code to the time (hours) in the CH register that you get from invoking the DOS function 2Ch.

How to loop through dates in Racket?

I want to loop through dates from the current date to some stop date, like the following example in Python:
import datetime
def count_dates(stop_date):
step = datetime.date.today()
while step >= stop_date:
yield step
step = step - datetime.timedelta(days=1)
def main():
for step in count_dates(datetime.date(2018, 1, 1)):
print(step.isoformat())
I don't see any date calculation functions in Racket, however. How can this be done?
If you want to use racket/date, you can accomplish your goal with find-seconds, seconds->date, current-seconds, and a simple arithmetic:
#lang racket
(require racket/date
racket/generator)
(define 1day (* 60 60 24))
(define (count-dates year month day)
(define target (find-seconds 0 0 0 day month year))
(in-generator
(let loop ([current (current-seconds)])
(when (>= current target)
(yield (seconds->date current))
(loop (- current 1day))))))
(date-display-format 'iso-8601)
(for ([dt (count-dates 2019 2 1)])
(displayln (date->string dt)))
This outputs:
2019-02-11
2019-02-10
2019-02-09
2019-02-08
2019-02-07
2019-02-06
2019-02-05
2019-02-04
2019-02-03
2019-02-02
2019-02-01
That is, from today (Feb 11, 2019) to Feb 1, 2019.
You can also use gregor or srfi-19 which are alternative date libraries that have a notion of time duration/difference.
Here is how you can do it using the date arithmetic provided by gregor. Specifically the +days and -days functions are helpful here:
#lang racket
(require gregor
racket/generator)
;; Date -> [Sequenceof Date]
(define (count-dates stop-date)
(in-generator
(let loop ([step (today)])
(when (date>=? step stop-date)
(yield step)
(loop (-days step 1))))))
(for ([step (count-dates (date 2018 1 1))])
(displayln (date->iso8601 step)))
And if you need something more general than "some number of days", there's also functions like +date-period and -date-period.

Chosing specific dates/hours from an array

I have a matrix that has 3months of data or so..Its a 952x1 matrix with the elements in the following format(3 hourly )
Aug-05-2015 03:00:00
Aug-05-2015 06:00:00
Aug-05-2015 09:00:00
Aug-05-2015 12:00:00
Aug-05-2015 15:00:00
Aug-05-2015 18:00:00
Aug-05-2015 21:00:00
Aug-06-2015 00:00:00
Aug-06-2015 03:00:00
Aug-06-2015 06:00:00
I would want to choose say only day timings/ only night or say for august month alone. How do i do that.
Further to my question, if I have a group of .wav files and Im trying to pick only month wise or do daily psd averages etc or chose files belonging to a month how to go about? The following are first 10 .wav files in a .txt file that are read into matlab code-
AMAR168.1.20150823T200235Z.wav
AMAR168.1.20150823T201040Z.wav
AMAR168.1.20150823T201845Z.wav
AMAR168.1.20150823T202650Z.wav
AMAR168.1.20150823T203455Z.wav
AMAR168.1.20150823T204300Z.wav
AMAR168.1.20150823T205105Z.wav
AMAR168.1.20150823T205910Z.wav
AMAR168.1.20150823T210715Z.wav
yyyymmddTHHMMSSZ.wav is part of the format to get sense of some parameters.
Thanks.
Are these datetimes? If so, you can use logical indexing here if you make use of some of the datetime functions. To get the times in August:
t = datetime(2015, 8, 1, 3, 0, 0) + hours(3:3:3000)';
t(month(t) == 8) % Times in August
To get the times that are during the day or night:
t(hour(t) < 12) % Day times
t(hour(t) >= 12) % Night times

Unix Time stamp day of the week pattern

If all I have is the unix timestamp and I am not able to use any functions to format it (such as day of the week or date) is there any known pattern by looking at the timestamp to deduce what day of the week it is?
for example perhaps all timestamps that are divisible by 150 are Mondays
The Unix Epoch (Jan 1, 1970, 00:00) was on a Thursday. Specifically it marked the beginning of a Thursday.
The first Monday after the Unix Epoch begins on Jan 5, 1970, 00:00. This is a UNIX timestamp of 96 hours.
The second Monday after the Unix Epoch begins on Jan 12, 1970, 00:00. This is a UNIX timestamp of 264 hours.
Let's assume X is your Unix timestamp in hours. The formula ((X - 96) % (264 - 96)) / 24 will return a zero-based weekday index where 0 is Monday and 6 is Sunday. The formula looks like this:
(X - 96) % 168 / 24 (if X is your timestamp in hours)
(X - 345600) % 604800 / 86400 (if X is your timestamp in seconds)
(X - 345600000) % 604800000 / 86400000 (if X is your timestamp in milliseconds)
If i experiment with exactly this moment, defined by a Unix timestamp of 1466710873523 ms i would get (1466710873523 - 345600000) % 604800000 / 86400000 which is ~3.8 (meaning it's Thursday) (almost Friday though :). Note though that it's Thursday UTC - in certain timezones it might be different so for local time you would need to take timezone offset into account.
From my own observations, the timestamp at midnight GMT ends in 000 every 6 days. The sequence is as follows: 000, 400, 800, 200, 600, 000, 400, 800, 200...
So, today (in UCT) started at 1465948800 and has been Wednesday.
So I know that that tomorrow's starting timestamp will end with 200 etc.
If you count the days from today (1465948800) to your desired date and divide by 6,
if the remainder is 1, the ending will be '200',
2: '600',
3: '000',
4: '400',
5: '800'.
Because a week has 7 days, if this Wednesday ended in 800, next Wednesday will end in 200 and the following wednesday in 600, etc.

MATLAB Cut 3D array of daily data into monthly segments

I have a 1437x159x1253 large matrix (let's call it A) of daily sea ice data for a little over 2 years. I need to write a code that takes the daily data from each month and does mean(A, 3) on it. So basically, 1253 is the t in days. If I start from January, I need to do mean(A,3) of the first 31 days, then the mean(A,3) of February, the next 28 or 29 days. Because the days alternate between 31 and 30 (and 28 or 29 for February), I don't know how to write a code to do this. I can do it manually, but that would take a while.
Thanks!
You can initialize an array containing the number of days in each month, Mon = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] using boolean to check whether it's a leap year (to set Mon(2) = 29). The number of days will help you index each month appropriately, using a loop like:
index=1;
for i=1:12
average = mean(A(:,:,index:(index+Mon(i)-1),3);
index = index+M(i); % Starting location of the next month
end