Carbon php date time math - laravel

I know when an account is created in UTC. If the account is cancelled before 2am PST the next day then the account needs to be removed, otherwise it is not removed until later. I'm having trouble coming up with the actual statements to use in Carbon. For example:
$account->getAttribute('created_at');
returns
Illuminate\Support\Carbon #1597790786 {#3432
date: 2020-08-18 22:46:26.0 UTC (+00:00),
}
Therefore I need to know if now() is >= 2020-08-19 02:00:00.0 PDT/PST.
How should I do that?

Switch your date in the timezone to consider "tomorrow 2am" then re-switch in UTC for the comparison:
$cancellation = $account->getAttribute('cancelled_at');
$creation = $account->getAttribute('created_at');
if ($cancellation < $creation->tz('PST')->modify('tomorrow 2am')->utc()) {
// remove
}

Related

How to get the same output of departed Date.parse() in groovy?

I have an application that runs the old version of the spring application. The application has the function to create date objects using Date.parse as follows
Date getCstTimeZoneDateNow() {
String dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
def zonedDateString = new Date().format(dateFormat, TimeZone.getTimeZone('CST'))
Date date = Date.parse(dateFormat, zonedDateString)
return date // Tue Oct 18 20:36:12 EDT 2022 (in Date)
}
However, the code above is deprecated. I need to produce the same result.
I read other posts and it seems like Calender or SimpleDateFormatter is preferred.
And I thought SimpleDateFormatter has more capabilities.
This post helped me understand more about what is going on in the following code
SimpleDateFormat parse loses timezone
Date getCstTimeZoneDateNow() {
Date now = new Date()
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
SimpleDateFormat sdf = new SimpleDateFormat()
sdf.setTimeZone(TimeZone.getTimeZone('CST'))
// cstDateTime prints times in cst
String cstDateTime = sdf.format(now) // 2022-10-18T20:36:12.088Z (in String)
// JVM current time
Date date = sdf.parse(cstDateTime) // Tue Oct 18 21:36:12 EDT 2022 (in Date)
return date
}
Here my goal is to return the date object that is in the format of Tue Oct 18 20:36:12 EDT 2022
The format is good. However, like the post says, when I do sdf.parse(), it prints in JVM time.
This means, the format is good but the time zone is off.
How can I get the exact same result as before?
It does not have to use SimpleDateFormatter. Could be anything.
Thank you so much for reading and for your time.
Perhaps the important thing is, that the Date is always neutral to the timezone. Given example shows what is to be expected to work from the Java specs:
def format = new SimpleDateFormat()
format.setTimeZone(TimeZone.getTimeZone("CST"))
println new Date()
def date = format.parse(format.format(new Date()))
printf "parsed to %s%n", date
printf "formatted to %s (%s)%n", format.format(date), format.getTimeZone().getDisplayName()
In the output, notice when using the Format and when the toString(), a different time is shown accordingly, which is perfectly fine, since first we format and then parse again in the same format, thus the same time-zone. Later, we use the Date.toString() to output the date, this time using the system default time-zone which is always used when Date.toString() is called. In the output, the time-zone shift is reflected:
Thu Oct 20 09:22:58 EDT 2022
parsed to Thu Oct 20 09:22:00 EDT 2022
formatted to 10/20/22 8:22 AM (Central Standard Time)

How reduce one day from current in Pipeline Jenkins?

I can't reduce one day from current
def now = new Date();
print(now); // print Fri Sep 06 13:10:03 EEST 2019
print(now - 1.days); // not working
print(now - 1); // not working
Please help me. Thanks in advance
the solution works. There might be 2 problems though:
- the snippet you wrote has to be included in a script if you plan to execute it in a stage
- the DateGroovyMethods is not allowed to be used by default. You need administrator rights and to check the build log to allow the execution of that stuff.
The error will look like this:
Scripts not permitted to use staticMethod org.codehaus.groovy.runtime.DateGroovyMethods minus java.util.Date int. Administrators can decide whether to approve or reject this signature.
This is my test example:
pipeline {
agent any
stages {
stage('MyDate test') {
steps {
script {
def date = new Date()
print date
print date - 1
}
}
}
}
}
EDIT:
If you are not an administrator, you can replace the script block with sh 'date -d "-1 days"'
You can also use minus(1) instead of - 1:
def now = new Date();
print(now);
print(now.minus(1))
The best thing to do is to skip the use of Date entirely. java.util.Date is literally the oldest java implementation of date and time. The newest comes with Java 8. You can do it like this:
groovy:000> java.time.LocalDateTime.now().minusDays(1)
===> 2019-09-08T12:07:30.835557
groovy:000>
You can convert from Date to LocalDateTime as well if needed.
(Java syntax used here, as I do not know Groovy.)
tl;dr
Subtract 24-hours.
Instant.now().minus( Duration.ofHours( 24 ) ) // UTC.
…or…
Subtract one calendar day.
ZonedDateTime.now( ZoneId.of( "America/New_York" ) ).minusDays( 1 ) ) // Time zone for Toledo, Ohio, US.
java.time
Never use java.util.Date. That terrible class was supplanted years ago by the modern java.time classes with the adoption of JSR 310. Specifically replaced by Instant.
I can't reduce one day from current
What do you mean by “one day”?
Generic 24-hour days
Do you mean to subtract 24-hours?
Duration d = Duration.ofHours( 24 ) ;
Instant instant = Instant.now() ;
Instant twentyFourHoursAgo = instant.minus( d ) ;
The Instant class represents a moment in UTC with a resolution of nanoseconds.
Run this code live at IdeOne.com.
instant.now().toString(): 2019-09-09T18:48:17.106438Z
twentyFourHoursAgo.toString(): 2019-09-08T18:48:17.106438Z
Calendar days
Do you mean to subtract one calendar day?
This requires a time zone. For any given moment, the date varies around the globe by time zone. It may be “tomorrow” in Tokyo Japan while still “yesterday” in Toledo Ohio US.
Specify a time zone with ZoneId to capture the current moment as seen through the wall-clock time used by the people of a particular region in a ZonedDateTime object.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
ZonedDateTime oneDayAgo = zdt.minusDays( 1 ) ;
Run this code live at IdeOne.com.
zdt.toString(): 2019-09-10T03:48:17.147539+09:00[Asia/Tokyo]
oneDayAgo.toString(): 2019-09-09T03:48:17.147539+09:00[Asia/Tokyo]
Convert
If you must have a java.util.Date object to interoperate with old code not yet updated to java.time, you can convert. See the new to…/from… conversion methods added to the old classes.
java.util.Date javaUtilDate =
Date.from( Instant.now().minus( Duration.ofHours( 24 ) ) ) ;
…or…
java.util.Date javaUtilDate =
Date.from( ZonedDateTime.now( ZoneId.of( "Asia/Tokyo" ) ).minusDays( 1 ) ) ) ;
Keep in mind that java.util.Date.toString method tells a lie, dynamically applying the JVM’s current default time zone while generating the text. One of many reasons to avoid this badly-designed class.

How can I return LocalDate.now() in milliseconds?

I create date now:
ZoneId gmt = ZoneId.of("GMT");
LocalDateTime localDateTime = LocalDateTime.now();
LocalDate localDateNow = localDateTime.toLocalDate();
Then I want return this date in milliseconds:
localDateNow.atStartOfDay(gmt) - 22.08.2017
localDateNow.atStartOfDay(gmt).toEpochSecond(); - 1503360000 (18.01.70)
How can I return LocalDate.now() in milliseconds?
Calling toInstant().toEpochMilli(), as suggested by #JB Nizet's comment, is the right answer, but there's a little and tricky detail about using local dates that you must be aware of.
But before that, some other minor details:
Instead of ZoneId.of("GMT") you can use the built-in constant ZoneOffset.UTC. They're equivalent, but there's no need to create extra redundant objects if the API already provides one that does exactly the same thing.
Instead of calling LocalDateTime.now() and then .toLocalDate(), you can call LocalDate.now() directly - they're equivalent.
Now the tricky details: when you call the now() method (for either LocalDateTime or LocalDate), it uses the JVM's default timezone to get the values for the current date, and this value might be different depending on the timezone configured in the JVM.
In the JVM I'm using, the default timezone is America/Sao_Paulo, and the local time here is 09:37 AM. So LocalDate.now() returns 2017-08-22 (August 22th 2017).
But if I change the default timezone to Pacific/Kiritimati, it returns 2017-08-23. That's because in Kiritimati, right now is already August 23th 2017 (and the local time there, at the moment I write this, is 02:37 AM).
So, if I run this code when the default timezone is Pacific/Kiritimati:
LocalDate dtNow = LocalDate.now(); // 2017-08-23
System.out.println(dtNow.atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());
The output is:
1503446400000
Which is the equivalent of August 23th 2017 at midnight in UTC.
If I run the same code when the default timezone is America/Sao_Paulo, the result will be:
1503360000000
Which is the equivalent of August 22th 2017 at midnight in UTC.
Using now() makes your code depends on the JVM's default timezone. And this configuration can be changed without notice, even at runtime, making your code return different results when such change occurs.
And you don't need such an extreme case (like someone misconfiguring the JVM to a "very-far" timezone). In my case, for example, in America/Sao_Paulo timezone, if I run the code at 11 PM, LocalDate will return August 22th, but the current date in UTC will already be August 23th. That's because 11 PM in São Paulo is the same as 2 AM of the next day in UTC:
// August 22th 2017, at 11 PM in Sao Paulo
ZonedDateTime z = ZonedDateTime.of(2017, 8, 22, 23, 0, 0, 0, ZoneId.of("America/Sao_Paulo"));
System.out.println(z); // 2017-08-22T23:00-03:00[America/Sao_Paulo]
System.out.println(z.toInstant()); // 2017-08-23T02:00:00Z (in UTC is already August 23th)
So using a LocalDate.now() is not a guarantee that I'll always have the current date in UTC.
If you want the current date in UTC (regardless of the JVM default timezone) and set the time to midnight, it's better to use a ZonedDateTime:
// current date in UTC, no matter what the JVM default timezone is
ZonedDateTime zdtNow = ZonedDateTime.now(ZoneOffset.UTC);
// set time to midnight and get the epochMilli
System.out.println(zdtNow.with(LocalTime.MIDNIGHT).toInstant().toEpochMilli());
The output is:
1503360000000
Which is the equivalent of August 22th 2017 at midnight in UTC.
Another alternative is to pass the timezone to LocalDate.now, so it can get the correct values for the current date on the specified zone:
// current date in UTC, no matter what the JVM default timezone is
LocalDate dtNowUtc = LocalDate.now(ZoneOffset.UTC);
// set time to midnight and get the epochMilli
System.out.println(dtNow.atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli());

Lua UTC time inconsistencies

Lua 5.1 doc says:
If format starts with '!', then the date is formatted in Coordinated
Universal Time.
If format is %c, !'s behavior seems correct
local date_1 = os.date("!%c")
local date_2 = os.date("%c")
print("utc date: "..date_1)
print("not utc date: "..date_2)
If format is *t, !'s behavior seems swapped
local time_1 = os.time(os.date("!*t"))
local time_2 = os.time(os.date("*t"))
print("should be utc time, but is not: "..time_1) -- this should be UTC, and is not
print("should not be utc time, but is: "..time_2) -- this should not be UTC, but is
Dates are tested with: http://www.epochconverter.com/
Why is that?
The table returned by os.date("!*t") and os.date("*t") is correct. I'm printing only the hour field. Note that they are consistent with %c format:
local date_1 = os.date("!%c")
local date_2 = os.date("%c")
print("utc date: "..date_1)
print("not utc date: "..date_2)
print("utc date hour: " .. os.date("!*t").hour)
print("not utc date hour: " .. os.date("*t").hour)
Output on my machine (China Standard Time, UTC+08:00):
utc date: 02/06/15 02:02:29
not utc date: 02/06/15 10:02:29
utc date hour: 2
not utc date hour: 10
However, os.time takes the table, assuming it's the local time, and returns the epoch. So, the local time is converted to the real epoch, but the utc time is not.
print(os.time{year=1970, month=1, day=1, hour=8})
outputs 0 on my machine.

Rails Time Zone and cron scheduling

I have an AWS server that runs daily cron jobs reporting on our user base. I want to ensure my report is run for the full day the previous day in MST. Currently I use this as the code for the data quering
Time.new(Time.now.year, Time.now.month, Time.now.day).yesterday.beginning_of_day.in_time_zone('MST)..Time.new(Time.now.year, Time.now.month, Time.now.day).yesterday.end_of_day.in_time_zone('MST)
I read it is bad practice to use Time.now as that is the system (UTC) time? I am wondering if what I am doing is a big no no or if there is a more efficient way?
thank you!
Mountain Standard Time is 7 hours behind UTC, so when you capture all the data points from the day of July 22rd in MST, you want the UTC times to be from 7/22 at 7:00AM UTC to 7/23 at 7:00AM UTC.
I don't think your code is correct because you are calling in_time_zone("MST") after beginning_of_day.
When you run this code on a server that is on UTC, the evaluated times are different:
>> Time.new.yesterday.beginning_of_day.in_time_zone('MST').utc
=> 2013-07-22 00:00:00 UTC
>> Time.new.in_time_zone("MST").yesterday.beginning_of_day.utc
=> 2013-07-22 07:00:00 UTC
Here is how you can determine the start and end times properly:
>> t = Time.new
=> 2013-07-23 19:45:10 +0000
>> start_time = t.in_time_zone("MST").yesterday.beginning_of_day
=> Mon, 22 Jul 2013 00:00:00 MST -07:00
>> end_time = t.in_time_zone("MST").yesterday.end_of_day
=> Mon, 22 Jul 2013 23:59:59 MST -07:00
When we convert the start and end times to UTC, we get the desired result.
>> start_time = t.in_time_zone("MST").yesterday.beginning_of_day.utc
=> 2013-07-22 07:00:00 UTC
>> end_time = t.in_time_zone("MST").yesterday.end_of_day.utc
=> 2013-07-23 06:59:59 UTC
I don't know what you are trying to do, but
Time.new(Time.now.year, Time.now.month, Time.now.day)
is definitely a terrible code fragment. For example, if the time lag between the execution time of Time.now.year and that of Time.now.month overlaps the moment of the change of the year, then the time object created with the main Time.new will be neither of the two moments. If you want to get the current time, just do
Time.new
or
Time.now
If you are trying to create a time range calculated out of a single time, then whatever your code should be, create time only once:
t = Time.now
and use that in the rest of your code:
t.some_method..t.some_other_method

Resources