I'm trying to figure out what the best way to store date in DB is. Using
new Date().getTime()
seems to be the most common but is it possible to get the year/month/date from the timestamp? or is getTime meant as a way to sort data. Should I just store new Date() directly if I want retrieve the y/m/d information again?
Thanks
var dateObject = new Date();
var year = dateObject.getYear();
var month = dateObject.getMonth();
var date = dateObject.getDate();
getTime() is useful for saving in files and databases because it represents the date and time as a single number, which is very compact. It's also represented in UTC, so the timezone doesn't matter.
You can convert it back to a Date with:
var thatTime = Date(retrievedTime);
Then you can use thatTime.getYear(), thatTime.getMonth(), etc. to extract parts of the saved time.
#Barmar is absolutely correct. However, if you want the year, month and date information stored in an easily readable way, you can go two ways (assuming you only want the date and not the time):
Use the Date object's getYear, getMonth and getDate methods respectively and store them in separate fields (less processing for display and you can choose which parts you want, but more parsing required for sorting, etc.)
toDateString (and toLocaleString for non-American-English and flexibility) gives a human-readable string like "Wed Jul 28 1993" (and then you'd slice off the first 4 characters).
Related
I have a very simple SQL string that brings a Date field from sql:
SELECT dbo.table.effDate from table where.....
I need to convert that date to a date variable at Node so I can perform a calculation. This date is always the first of a month, so my results at SQL are
2023-01-01
2022-05-01
2022-08-01
etc.
So, when I try to convert the field to a node date type, in these different ways, I always get the previous date of the one at the field (for the example above)
2022-12-31
2022-04-30
2022-07-31
Im using:
let effDate = moment(response[i].effDate, 'YYYY-MM-DD').format('YYYY-MM-DD')
Then
let effDate = new Date(response[i].effDate)
even this is bringing me a previous date
let effDate = response[I].effDate.toString()
and this:
let effDate = new Date(response[I].effDate).toLocaleDateString('en-US')
I could fix this by adding one day to whatever SQL brings me back, but its not the point, I want to do it right.
I also tried using getTimezoneOffset
effDate = new Date(response[i].effdate.getTime() - response[i].effdate.getTimezoneOffset() * 60000)
But I always get the previous date.
What confuses me is that javascript UTC zones should have nothing to do when it comes to the value returned by SQL:
Again, I could just add a day but that wont be right, and I would like to know why this is happening (even using toString()).
Thanks.
Basically Date treats strings as being the UTC representation of that moment in time (because its the standard format to save a date in a database). Running the following line should give you a better understanding of this:
console.log(new Date('2023-01-01').toString())
I get:
Sat Dec 31 2022 16:00:00 GMT-0800 (Pacific Standard Time)
Either allow moment.js to interpret the string directly, or use the .utc() method.
// moment from Date object is still UTC, outputs local
console.log('A:', moment(new Date('2023-01-01')).format('YYYY-MM-DD'))
// moment parses string assumming local
console.log('B:', moment('2023-01-01').format('YYYY-MM-DD'))
// use moment.utc() method to keep output UTC
console.log('C:', moment(new Date('2023-01-01')).utc().format('YYYY-MM-DD'))
console.log('D:', moment.utc(new Date('2023-01-01')).format('YYYY-MM-DD'))
console.log('E:', moment.utc('2023-01-01').format('YYYY-MM-DD'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
Lets say I have the following timezone aware Date objects in Javascript:
var date1 = new Date("2019-07-02T07:30:00-05:00");
var date2 = new Date("2020-08-05T00:00:00-05:00");
What is the best way to merge these two, such that I keep the time from date1 and the date from date2, yielding:
new Date("2020-08-05T07:30:00-05:00");
I've tried:
date1.setDate(date2.getDate());
date1.setMonth(date2.getMonth());
date1.setYear(date2.getYear());
which set the day and month correctly for date1, but the year is incorrectly set to "120" with the example inputs above.
A few things:
Date objects cannot be time zone aware. When passed a string with a time zone offset like the ones you showed here, they use that offset to determine the equivalent UTC time. Ultimately the only thing stored within the Date object is the numeric Unix timestamp that corresponds to that UTC time. You can see this with .getTime() or .valueOf().
getDay/setDay are for the day of the week, Saturday (0) through Sunday (6). Use getDate/setDate for the day of the month.
getYear/setYear are for two-digit years (or rather the current year minus 1900), and should not be used ever. Use getFullYear/SetFullYear instead.
Because of the first point, what you ask is not possible. Or at least, not possible with the full range of values that might be encountered in such strings. Instead, you can manipulate the strings directly, or you can use a library such as Luxon or Moment.
I'd also think a bit harder about what you're actually trying to accomplish. Where do these two values come from? Why are portions of the data important and others to be discarded? What will you do if the offsets are different between the two values? Only you can answer these points.
Manipulate the ISO strings directly:
const date1 = new Date("2019-07-02T07:30:00-05:00");
const date2 = new Date("2020-08-05T00:00:00-05:00");
const date3 = new Date([
date2.toISOString().split('T')[0],
'T',
date1.toISOString().split('T')[1],
].join(''));
console.log({date1, date2, date3});
By the way, there is no "timezone-aware" date objects. Once Date(...) is fired, time is UTC. getTimezoneOffset gets the difference from the local timezone to UTC.
I've read this question:
How do you convert a JavaScript date to UTC?
and based on this I implemented this conversion in a dateTools module as follows:
[Update]
var dt, utcTime;
dt = new Date();
utcTime = new Date(Date.UTC(dt.getFullYear(),
dt.getMonth(),
dt.getDate(),
dt.getHours(),
dt.getMinutes(),
dt.getSeconds(),
dt.getMilliseconds()));
Now I'd like to write unit tests. My idea was to check whether the result is actually in UTC, but I don't know how.
All the toString, toUTCString and similar methods seem to be identical for the input (non UTC) and output (UTC) date.
Only the result of the getTime method differs.
Is there a way to check wheter a date is UTC in javascript? If not, is there a better idea to unit test this?
To give more context:
Only converting the it to a UTC string is not that helpful, because in the next step the date is sent to an Asp.net service and therefore converted to a string like:
'/Date([time])/'
with this code
var aspDate = '/Date(' + date.getTime() + ')/';
var aspDate = '/Date(' + date.getTime() + ')/';
This outputs the internal UNIX epoch value (UTC), which represents a timestamp. You can use the various toString methods to get a more verbose string representation of that timestamp:
.toString() uses the users timezone, result is something like "Fri Jan 25 2013 15:20:14 GMT+0100" (for me, at least, you might live in a different timezone)
.toUTCString() uses UTC, and the result will look like "Fri, 25 Jan 2013 14:20:15 GMT"
.toISOString() uses UTC, and formats the datestring according to ISO: "2013-01-25T14:20:20.061Z"
So how do we construct the time value that we want?
new Date() or Date.now() result in the current datetime. No matter what the user's timezone is, the timestamp is just the current moment.
new Date(year, month, …) uses the users timezone for constructing a timestamp from the single values. If you expect this to be the same across your user community, you are screwed. Even when not using time values but only dates it can lead to odd off-by-one errors.
You can use the setYear, setMonth, … and getYear, getMonth … methods to set/get single values on existing dates according to the users timezone. This is appropriate for input from/output to the user.
getTimezoneOffset() allows you to query the timezone that will be used for all these
new Date(timestring) and Date.parse cannot be trusted. If you feed them a string without explicit timezone denotation, the UA can act random. And if you want to feed a string with a proper format, you will be able to find a browser that does not accept it (old IEs, especially).
Date.UTC(year, month, …) allows you to construct a timestamp from values in the UTC timezone. This comes in handy for input/output of UTC strings.
Every get/set method has a UTC equivalent which you can also use for these things.
You can see now that your approach to get the user-timezone values and use them as if they were in UTC must be flawed. It means either dt or utcTime has the wrong value, although using the wrong output method may let it appear correct.
getTimezoneOffset
Syntax: object.getTimezoneOffset( ) This method
returns the difference in minutes between local time and Greenwich
Mean Time. This value is not a constant, as you might think, because
of the practice of using Daylight Saving Time.
i.e.
var myDate = new Date;
var myUTCDate = new Date(myDate - myDate.getTimezoneOffset() * 60000);
alert(myUTCDate);
note: 60000 is the number of milliseconds in a minute;
I want to do a straight conversion of a date string and cannot get the results I expect. I expect the below code to produce a date equal to the date portion of the original string, but it seems to apply a time during the instance creation.
var usageTime = new Date('2012-01-19T22:59:50-0800');
console.log(usageTime); // Fri, 20 Jan 2012 06:59:50 GMT
dayOfUsage = usageTime.getFullYear()+'-'+(usageTime.getMonth()+1)+'-'+usageTime.getDate();
console.log(dayOfUsage); // 2012-1-20
I expect a date of 2012-1-19. What is the right way to solve this?
You should use getUTC*() functions (getUTCDate(), getUTCHours() and so on) to get your times with no timezone offset.
I have the following code:
$(function () {
var thedate = "/Date(1198908717056)/";
var thedate2 = ProcessDate(thedate)
alert(thedate2);
});
function ProcessDate(DateString) {
var TheDate = eval(DateString.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));
return TheDate;
}
When it runs, it returns an alert with December 29 and the time is showing as Eastern Time. When I change the timezone on my computer, it's still showing the date in the Eastern timezone.
My question is this: does the string "/Date(1198908717056)/" contain the timezone information or is the timezone displayed in the alert the result of the browser determining my timezone?
Thanks.
JSON doesn't have dates at all (it's one of JSON's flaws). Those strings are just strings.
Some frameworks, like ASP.Net, use that syntax to indicate dates. What timezone they're in will be dictated by the framework. I believe the dates are in UTC and so you can just use the new Date(Number) constructor to create them (more in this other answer). That creates the date by directly setting its internal "milliseconds since The Epoch UTC" value, more in section 15.9 of the specification. Mind you, that only works if, in fact, whatever it is creating these pseudo-date strings is using UTC.
Update: Looking at your code, although it works, this line:
var TheDate = eval(DateString.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));
...is an abuse of eval. eval should be avoided whenever possible. Instead, if you want to keep it as a one-liner:
var TheDate = new Date(Number(DateString.replace(/\/Date\((\d+)\)\//gi, "$1")));
...or somewhat more readably:
var Match = /\/Date\((\d+)\)\//gi.exec(DateString);
var TheDate;
if (Match) {
TheDate = new Date(Number(Match[1]));
}
In all of those cases, the Date will be initialized with the UTC time value embedded in the date string. But then when you ask JavaScript to format the date (for instance, via toString), it will use your local timezone to do that. You haven't shown how you're outputting the date, so I can't tell you why the timezone seems not to change if you change your timezone (perhaps the browser didn't pick up the change?). When I do it, if I output the date as a string, it shows it in British Summer Time (which is my current timezone) if I use toString, or UTC if I use toUTCString. Here's a live example using both your original date, and a date (today's date, as I write this) that's in daylight savings time so even in the UK you can see the difference between UTC and local time.
Off-topic: In JavaScript, the overwhelming convention is to use camelCased names starting with a lower-case letter for both local variables and function names. So, theDate rather than TheDate. Initial caps are reserved for constructor functions (like Date). You're free to ignore the convention, of course, but it will tend to make it difficult for others to read your code.
The timezone is taken from your current system setting. Have a look at the Date class.
The given value is in milliseconds and does not contain a timezone. The constructor of Date() expects the milliseconds to be given in UTC. If you have values with a known timezone, you should use the dateString constructor version.
However, as far as I know, there is no way convert between timezones in JavaScript, except for UTC and the local system timezone.