How to become a time lord - Time travel
Time travel is like visiting Paris. You can't just read the guide, you have to throw yourself into it. Eat the food, use the wrong verbs, get double the charges, and end up kissing complete strangers.
The Doctor
We are now going to travel through time, that is, we are going to see future and past dates and how to calculate them in different formats. The TARDIS doesn't wait, take the controls and hold on tight.
Let's go to tomorrow
as we saw in the previous article, The date in internal format is divided into the number of days since January 1, 1841 and the number of seconds since 00:00 hours.
If we want to increase a day, we can think... by adding a value or subtracting it from the date part... I'm already traveling through time.
SET Today = $ZDATE($HOROLOG,4)
SET InternalDate = $ZDATEH(Today, 4)
SET Future = InternalDate + 2
SET FutureDate = $DATE(Future, 4)
WRITE "Today: "_Today,!,"Internal date: "_InternalDate,!,"Future: "_Future,!,"Future date: "_FutureDate
> Today: 02/09/2022 Internal date: 66149 Future: 66151 Future date: 04/09/2022
How easy... you know how to move through the days. But if you want to go the following month, things change. The calendar does not have the same number of days from one month to another, so it is not worth adding 30 days to the date. Let me introduce you to our command to add or subtract time parts.
If you are a T-SQL user you'll see that the command will sound quite familiar to you: DATEADD.
It's part of the library $SYSTEM.SQL.Functions
Back to the future
We can add months, days, years... or remove it from the indicated date.
SET InternalDate = $ZDATEH("09/02/2022", 4)
SET Future = $SYSTEM.SQL.DATEADD("mm",1,InternalDate)
WRITE "InternalDate "_InternalDate,!,"Future: "_Future
InternalDate: 66149 Future: 2022-03-09 00:00:00
If we want to remove days, months and years we would have to do it in parts, each of the steps separately
Set InternalDate = $ZDATEH("09/02/2022", 4)
Set PastDays = $SYSTEM.SQL.DATEADD("dd",12,InternalDate)
Set PastMonths = $SYSTEM.SQL.DATEADD("mm",8,PastDays)
Set PastYears = $SYSTEM.SQL.DATEADD("yy",-7,PastMonths)
WRITE PastYears
2015-10-21 00:00:00
Mc Fly, Are you there??
It's my birthday right now, or not...
If what we want is to know what is the difference between two dates, we will use the command DATEDIF.
Set internalDate = $ZDATEH("09/02/2022", 4)
Set myBirthday = $ZDATEH("01/02/2023", 4)
Set days = $SYSTEM.SQL.DATEDIFF("dd",internalDate, myBirthday)
WRITE !days," days left until my birthday"
> 357 days left until my birthday
Well, look how good... we already know how to see the difference between two dates by days, months, years, etc...
I want to see Christopher Columbus discover America
Well, as we have said, our time format has the value 1 for 01/01/1841, and Christopher Columbus arrived in America on Oct. 12th 1492, so you will think... well, I am putting negative values to the date of 1 up to 1492
WRITE $ZDATE(-1)
<VALUE OUT OF RANGE>
Opss... Houston, we have a problem. We can't use negative values to get a date before 1841. Well, I do the conversion from text date to internal format and see what it returned.
WRITE $ZDATEH("12/10/1492",4) // European format
<VALUE OUT OF RANGE>
MMMEEEECCC !!! Thanks for competing, but it is not the correct answer.
How can we solve it?
This is because the dates have a defined minimum value that prevents going further, so if we use the mindata parameter it will allow us to use negative values in the internal format.
WRITE $ZDATEH("12/10/1492",4,,,,,-672045)
> -127184
The value that has been placed in the 7th position of the parameters indicates that the minimum accepted value will be -672045, to satisfy your curiosity, it corresponds to 01/01/0001, it is also the minimum number that we can use.
If you find that you get lost when counting "commas" to add this parameter, you can configure the National Language Support, NLS, and you leave it active.
SET originalValue= ##class(%SYS.NLS.Format).GetFormatItem("DateMinimum")
WRITE originalValue,!
DO ##class(%SYS.NLS.Format).SetFormatItem("DateMinimum", -672045)
WRITE $ZDATEH("12/10/1492", 4),!
DO ##class(%SYS.NLS.Format).SetFormatItem("DateMinimum", originalValue) // Return to the minimum value originally established
> 0
-127184
Then, you can now travel through time without problems.
Next article: Universal time
Acknowledgment
Thanks to @Robert Cemper for his article on negative $Horolog, which has helped me to complete this article and which you can see in the following link
https://community.intersystems.com/post/date-dec1840-negative-horolog