Why isn't my Unix time parsing consistently? - time

My client generates a timestamp using Date.now(), generating a unix time in milliseconds. But when I parse it later on the server, I get a very different date. I can reproduce this discrepancy with Jsfiddle. My code is:
const parseMoment = moment('1603551654605', 'x').format();
const parseDate = new Date(1603551654605).toDateString();
alert(`moment: ${parseMoment}, date: ${parseDate}`);
The output I get is: moment: 2020-11-16T00:00:00+01:00, date: Sat Oct 24 2020
The correct output is what moment gives me here, 11/16. But moment on my server actually gives me the incorrect October date. I need to reliably parse my unix timestamp back to the correct (later) date.

The unix timestamp converts to Saturday, 24 October 2020 15:00:54.605 (GMT)
momentJS does't require any second parameters while creating a date from milliseconds (DOCS).
Using the correct conversion, both moment() and new Date() show the same result:
const parseMoment = moment(1603551654605).format();
const parseDate = new Date(1603551654605).toDateString()
console.log(`moment\t: ${parseMoment}`);
console.log(`date\t: ${parseDate}`);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
moment : 2020-10-24T17:00:54+02:00
date : Sat Oct 24 2020

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)

Compare one date value with other dates and perform conditional action in cypress

I'm trying to compare one date value (ie. base value) with all other date values on a page and based on the difference between these days, I want to execute other commands.
Well, in the above UI, the base value is 11 Jul 2021 (Departure date in the first list) and other date values are 12 Jul 2021, 20 Jul 2021, 27 Jul 2021, 3 Aug 2021 and so on (Arrival dates from 2nd list onwards).
Now, I had to delete the all list(s) where the date difference between the base value and particular list is less than 15 days.
In this case, 12 Jul 2021, 20 Jul 2021 had to be deleted and all lists from 27 Jul 2021, 3 Aug 2021 and so on should be untouched as in the below picture.
So far, I have captured the value of the base value and came up with logic to compare it with another date value but I am not sure how I can save the 2nd and further date value(s) to a variable in order to compare with the base value.
{
cy.get("[data-test='departureTime']")
.eq(0)
.then((date) => {
const depDate_FirstPort = new Date(date.text());
cy.log(depDate_FirstPort.toISOString()); //2021-07-11T19:00:00.000Z
// const arrDate_SecondPort = new Date(cy.get('[data-test="arrivalTime"]').eq(1).invoke('text'));
// Since the above approach does not work, hard coding now.
const arrDate_SecondPort = new Date("22 Jul 2021 12:01")
cy.log(arrDate_SecondPort.toISOString()); //2021-07-22T10:01:00.000Z
cy.getDifferenceBetweenDates(depDate_FirstPort,arrDate_SecondPort).then((dif)=>{
if(dif < 16) {
cy.log("delete the port entry");
//do something
}
});
});
}
Cypress Command:
Cypress.Commands.add("getDifferenceBetweenDates", (Date1, Date2) => {
var diff_times = Math.abs(Date1.getTime() - Date2.getTime());
var diff_days = Math.ceil(diff_times / (1000 * 3600 * 24));
cy.log(diff_days) //11
})
Also, curious to know a possible approach to iterate all list falls under the 'to be deleted list' (12 Jul 2021, 20 Jul 2021) based on the condition mentioned above.
The iterative approach you have is ok, but you need to repeat the code you have for the first date to get the subsequent dates.
So, this bit but changing the index
cy.get("[data-test='departureTime']")
.eq(0) // 1,2,3 etc
.then((date) => {
A different approach is to filter the whole set,
const dayjs = require('dayjs') // replaces Cypress.moment
// first install with
// yarn add -D dayjs
it('finds the skipped ports', () => {
// helper func with format specific to this website
const toDate = (el) => dayjs(el.innerText, 'D MMM YYYY HH:mm')
cy.get("[data-test='departureTime']")
.then($departures => {
const departures = [...$departures] // convert jQuery object to an array
const first = toDate(departures[0]);
const cutoff = first.add(15, 'day')
const nextPorts = departures.slice(1) // all but the first
const skipPorts = nextPorts.filter(port => toDate(port).isBefore(cutoff))
expect(skipPorts.length).to.eq(2)
expect(skipPorts[0].innerText).to.eq('12 Jul 2021 14:02')
expect(skipPorts[1].innerText).to.eq('21 Jul 2021 04:00')
})
})
I'm not clear about your goal, but if you are going to actually delete the skipPorts from the page instead of just testing them, you should be wary of the DOM list changing as you do so.
Deleting from the list you have recently queried with cy.get("[data-test='departureTime']") would cause the internal subject to become invalid, and you might get "detached from DOM" errors or delete the wrong item.

What is this time format? (10 digits, 5 decimals)

So a website that I'm using has a websocket and they provide the broadcast time in the following manner:
"broadcasted_at":1574325570.71308
What is this time format and how do they generate it?
Unix epoch time ... the number of seconds that have elapsed since the Unix epoch, that is the time 00:00:00 UTC on 1 January 1970
now : 1574327074 : Thu Nov 21 03:04:34 2019
start of day : 1574316000 : Thu Nov 21 00:00:00 2019
1574325570 : 1574325570 : Thu Nov 21 02:39:30 2019
convert online : https://www.epochconverter.com/
... or download code (to build) to have command line program to perform the conversion https://github.com/darrenjs/c_dev_utils
I'm guessing the fractional part is the number of microseconds within the current second.
… and how do they generate it?
I don’t know, of course, what language or libraries your website is using. So this is just an example. To generate a value like 1574325570.71308 in Java:
Instant now = Instant.now();
double epochSeconds = now.getEpochSecond()
+ (double) now.getNano() / (double) TimeUnit.SECONDS.toNanos(1);
String result = String.format(Locale.ROOT, "%f", epochSeconds);
System.out.println("result: " + result);
When I ran this snippet just now (2019-12-15T11:18:01.562699Z), the output was:
result: 1576408681.562699
If you want exactly 5 decimals always another way is to use a DateTimeFormatter:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.INSTANT_SECONDS)
.appendPattern(".SSSSS")
.toFormatter();
String result = formatter.format(now);
result: 1576408681.56269

How to get timestamp for converted i18n date using momentjs

I'm using momentjs with timezone.
I've converted date to i18n using moment.locale('pt');
Now I want to get timestamp of the date. I get date value as converted i18n date, i.e. Ago 14 2018 22:00
I tried with moment("Ago 14 2018 22:00").tz("Asia/Calcutta").unix() => this is returing NaN
But this is working => moment("Aug 14 2018 22:00").tz("Asia/Calcutta").unix()
So how can I get timestamp of converted i18n date??
Here is fiddle of the problem : http://jsfiddle.net/uq99udc9/10265/
You need to first specify a locale as per momentJS documentation.
You also need to make sure you have that locale and if not import it.
Here is an example:
moment.locale('fr')
var date = moment("14 août 2018 10:37", "DD MMM YYYY hh:mm", "fr").format('LLL')
console.log(date);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/locale/fr.js" charset="UTF-8"></script>

Rails DateTime gives invalid date sometimes and not others

I've got a bunch of user-inputted dates and times like so:
date = "01:00pm 06/03/2015"
I'm trying to submit them to a datetime column in a database, and I'm trying to systemize them like this:
DateTime.strptime(date, '%m/%d/%Y %H:%M')
But I consistently get an invalid date error. What am I doing wrong? If I submit the string without strptime the record will save but it sometimes gets the date wrong.
Also, how can I append a timezone to a DateTime object?
Edit:
So .to_datetime and DateTime.parse(date) work for the date string and fail for date2. What's going on?
date2 = "03:30pm 05/28/2015"
Try using to_datetime:
date.to_datetime
# => Fri, 06 Mar 2015 13:00:00 +0000
Also if you read the documentation for DateTime#strptime, here. It states:
Parses the given representation of date and time with the given
template, and creates a date object.
Its important to note that the template sequence must match to that of input string sequence, which don't in your case - leading to error.
Update
Using to_datetime over second example will generate
ArgumentError: invalid date
This is because it expects the date to be in dd-mm-yy format. Same error will be raised for DateTime.parse as to_datetime is nothing but an api for the later. You should use strptime in-case of non-standard custom date formats. Here:
date2 = "03:30pm 05/28/2015"
DateTime.strptime(date2, "%I:%M%p %m/%d/%Y")
# => Thu, 28 May 2015 15:30:00 +0000
date = "01:00pm 06/03/2015"
DateTime.parse(date)
=> Fri, 06 Mar 2015 13:00:00 +0000
You haven't got your parameters in the correct order.
DateTime.strptime(date, '%H:%M%p %m/%d/%Y')
You'll also need to add %p for the am/pm suffix

Resources