Groovy Time durations - datetime

I'm trying to get the difference between 2 dates in days, hours, and seconds:
import groovy.time.*
Date now = new Date()
// Using deprecated constructor just for this example
Date newYearsDay2000 = new Date(2000, 0, 1)
use (TimeCategory) {
now - newYearsDay2000
}
This prints:
-690023 days, -14 hours, -38 minutes, -27.182 seconds
Which is obviously nothing like the difference between today's date and 2000/1/1, where am I going wrong?
Thanks,
Don

Could be an issue with the deprecated constructor?
If you use Calendar (and the Groovy updated method) to create the newYearsDay2000 var, you get:
import groovy.time.*
import static java.util.Calendar.*
Date now = new Date()
// Use the static imported Calendar class
Date newYearsDay2000 = instance.updated( year:2000, month:JANUARY, day:1 ).time
use( TimeCategory ) {
now - newYearsDay2000
}
which gives the result:
3925 days, 23 hours, 59 minutes, 59.999 seconds
Edit
Yeah, the JavaDoc for Date shows that constructor with the comment:
Date(int year, int month, int date)
Deprecated. As of JDK version 1.1, replaced by Calendar.set(year + 1900, month, date) or GregorianCalendar(year + 1900, month, date).
Which leads me to believe that:
Date newYearsDay2000 = new Date(2000, 0, 1)
Is actualy creating the Date for new Years Day in the year 3900

Date
Parameters:
year - the year minus 1900.

Related

How to parse a timestamp used by PRTG

I have a datetime string this format
44340.5416666667 but i want to convert this to 5/24/2021 3:00:00 PM - 4:00:00 PM format. How can i parse that with golang? I tried some convert function but it didn't work.
According to https://kb.paessler.com/en/topic/1313-how-do-i-translate-prtg-timestamp-values-format-to-normal-time-format, the timestamp format used by PRTG seems to be defined as the value of days since Dec 30, 1899.
Following the above link, the following Go code should convert the timestamp into a Go Time instance:
prtg := 44340.5416666667
// substract number of days between Dec 30, 1899 and Jan 1, 1970 and convert to millis
millis := int64((prtg - 25569) * 86400 * 1000)
t := time.Unix(0, millis*int64(time.Millisecond))
println(t.Format("1/2/2006 03:04:05 PM"))
According to prtg timestamp mentioned in Gregor Zurowski's comment,
convert your time to nano seconds (minimum unit in time to more accurate) and add unix nano of 1899-12-30 12.00 midnight.
re convert it to time and format it as below
package main
import (
"fmt"
"time"
)
func main() {
startDate := time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC).UnixNano()
timeVar := 44340.5416666667 //your time variable
duration := startDate + int64(float64(24*60*60) * timeVar * 1e9) //duration since start date in nanoseconds
fmt.Println(time.Unix(0, duration).Format("1/2/2006 03:04:05 PM"))
}

Start of previous year

**DATE FROM:**
def format=new java.text.SimpleDateFormat("yyyyMMdd")
def cal=Calendar.getInstance()
cal.get(Calendar.YEAR);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 31);
[format.format(cal.getTime())]
**DATE TO:**
def format=new java.text.SimpleDateFormat("yyyyMMdd")
def cal=Calendar.getInstance()
cal.add(Calendar.DAY_OF_MONTH,-cal.get(Calendar.DAY_OF_MONTH))
[format.format(cal.getTime())]
when year changes (2020 - 2021) - it confuses January of previous year with January of this year
I have to correct so that in January (December reporting) it extracts data for period 31.01 - 31.12. of previous year.
The job was wrong because it extracted data from 31.01.2021 to 31.12.2020
// retrieve details of the current date
def cal = Calendar.instance;
def currentYear = cal.get(Calendar.YEAR);
def currentMonth = cal.get(Calendar.MONTH);
// set the instance to the start of the previous month
if ( currentMonth == 0 ) {
cal.set(currentYear-1, 11, 1);
} else {
cal.set(currentYear, (currentMonth-1), 1);
}
// extract the date, and format to a string
Date previousMonthStart = cal.time;
String previousMonthStartFormatted = previousMonthStart.format('yyyy-MM-dd');
If all you are looking for is the start of the previous year as in your title then the following code:
import java.time.*
def startOfPreviousYear = LocalDate.now()
.withDayOfMonth(1)
.withMonth(1)
.minusYears(1)
println startOfPreviousYear
def againStartingFromJanuary = LocalDate.of(2021, 1, 15)
.withDayOfMonth(1)
.withMonth(1)
.minusYears(1)
println againStartingFromJanuary
demonstrates one way to accomplish this. When run, this prints (with now being today's date of 2021.Mar.10):
─➤ groovy solution.groovy
2020-01-01
2020-01-01
updated after comments
You can get the end of previous and current months with something like this:
import java.time.*
def endOfPreviousMonth = LocalDate.now()
.withDayOfMonth(1)
.minusDays(1)
def endOfCurrentMonth = LocalDate.now()
.withDayOfMonth(1)
.plusMonths(1)
.minusDays(1)
println "end of last month: ${endOfPreviousMonth}"
println "end of current month: ${endOfCurrentMonth}"
which with current date prints:
end of last month: 2021-02-28
end of current month: 2021-03-31
or if we are in january:
def endOfPreviousMonth = LocalDate.of(2021, 1, 15)
.withDayOfMonth(1)
.minusDays(1)
def endOfCurrentMonth = LocalDate.of(2021, 1, 15)
.withDayOfMonth(1)
.plusMonths(1)
.minusDays(1)
println "end of last month: ${endOfPreviousMonth}"
println "end of current month: ${endOfCurrentMonth}"
which prints:
─➤ groovy solution.groovy
end of last month: 2020-12-31
end of current month: 2021-01-31
In general you should try to, when possible, stay away from using manual date arithmetic when dealing with dates if your target is based on the current date (as in, previous month, next month, three months ago, etc). Use the api:s handed to you by java. The date classes take care of rolling years, rolling months, rolling days, leap years, etc, all that stuff that you really do not want to spend time solving yourself.

Groovy: Time in ISO 8601 format

How to get the current time and 15 min ago time in iso 8601 format (YYYY-MM-DDTHH:mm:ss) in groovy?
You can use java time's Instant and the toString() format
import java.time.*
def now = Instant.now()
def fifteenAgo = now.minus(Duration.ofMinutes(15))
println "Now is ${now} and 15 mins ago was ${fifteenAgo}"
Prints:
Now is 2020-06-30T19:53:17.445039Z and 15 mins ago was 2020-06-30T19:38:17.445039Z
You can formast the date in any way you want in Groovy, by doing e.g.
println new Date().format("yyyy-MM-dd HH.mm.ss.SSSSS Z")
Then, you can do calculations on the date, like this:
new Date(System.currentTimeMillis()-91*60*1000)
which will minus 91 minutes (91min * 60sec * 1000ms).
Then you can put the statements together, which is why Groovy is great:
def a = new Date(System.currentTimeMillis()-91*60*1000).format("YYYY-MM-DD")
And so you can get the half before the T. And the half after the T:
def b = new Date(System.currentTimeMillis()-91*60*1000).format("HH:mm:ss")
And then concatenate them with a T:
println "91 minutes ago in iso 8601 format is: ${a}T${b}"
There are other ways of doing it, like with TimeCategory.minus, but this is a good illustration. I used 91 minutes, but you can adapt it to your own requirtement.

Check whether a timestamp is 1 hour old - Groovy

I have a timestamp (submitTime) which I need to check whether it is less than 1 hour old or not. Timestamps are in microseconds and including date.
currentTime = 1527530605357000000 (Monday, May 28, 2018 6:03:25.357 PM)
submitTime = 1527529918658907821 (Monday, May 28, 2018 5:51:58.659 PM)
long currentTime = (long) (new Date().getTime()*1000000)
submitTime = job.SubmitTime // part of the code
oneHhour = 3600000000
if (currentTime - submitTime > oneHhour) {
println job.Name + " env is up more than 1 hour";
But it doesn't work since the result is 686698092179 and it it not represent time.
Help?
Assuming SubmitTime is a timestamp in microseconds, you can compare it the the current timestamp in microseconds like so:
// Get the current time (System.currentTimeMillis) in microseconds:
long currentMicroseconds = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis())
// You could also simply do this:
long currentMicroseconds = System.currentTimeMillis() * 1000
// Subtract the timestamps and compare:
if (currentMicroseconds - job.SubmitTime > 3600000000) {
// More than an hour has elapsed
}
The timestamp is assumed to be the number of microseconds since January 1, 1970, 00:00:00 GMT (consistent with Date.getTime).
In groovy you can use TimeCategory which is much more intuitive:
def date = new Date(timestampInLong)
use (groovy.time.TimeCategory) {
println (date > new Date() - 1.hour)
}

Weird flex date issue

Flex is driving me CRAZY and I think it's some weird gotcha with how it handles leap years and none leap years. So here's my example. I have the below dateDiff method that finds the number of days or milliseconds between two dates. If I run the following three statements I get some weird issues.
dateDiff("date", new Date(2010, 0,1), new Date(2010, 0, 31));
dateDiff("date", new Date(2010, 1,1), new Date(2010, 1, 28));
dateDiff("date", new Date(2010, 2,1), new Date(2010, 2, 31));
dateDiff("date", new Date(2010, 3,1), new Date(2010, 3, 30));
If you were to look at the date comparisons above you would expect to get 30, 27, 30, 29 as the number of days between the dates. There weird part is that I get 29 when comparing March 1 to March 31. Why is that? Is it something to do with February only having 28 days? If anyone has ANY input on this that would be greatly appreciated.
public static function dateDiff( datePart:String, startDate:Date, endDate:Date ):Number
{
var _returnValue:Number = 0;
switch (datePart) {
case "milliseconds":
_returnValue = endDate.time - startDate.time;
break;
case "date":
// TODO: Need to figure out DST problem i.e. 23 hours at DST start, 25 at end.
// Math.floor causes rounding down error with DST start at dayOfYear
_returnValue = Math.floor(dateDiff("milliseconds", startDate, endDate)/(1000 * 60 * 60 * 24));
break;
}
return _returnValue;
}
This is not a leap year problem, but rather a daylight savings time problem.
To correct the code to account for DST, you need to look at the timezoneOffset of both dates to determine if the date range is spanning a DST boundary.
var adjustment:Number = ( startDate.timezoneOffset - endDate.timezoneOffset ) * 60 * 1000;
_returnValue = endDate.time - startDate.time + adjustment;
This will get the difference between the two time zones (in minutes), convert that value to milliseconds, and then apply the timezone difference to the millisecond difference to "cancel out" the DST boundary.
Naturally, when both numbers are in the same time zone, the adjustment value becomes 0 and the time values are not adjusted.
You have part of the answer in your comment: 2010-Mar-01 0:00 until 2010-Mar-31 0:00 is thirty (!) days minus one hour (because Mar 14 is DST start in 2010). Since you floor the result of your division, you get 29.
Edit: This answer is of course based on the assumption that the time property of Date takes DST into account. This would explain your problem; I didn't check it, however.

Resources