It is possible to disable the daylight timezone conversion in moment.js?
http://plnkr.co/edit/MjFelt?p=preview
$scope.obj.date = moment('2016-06-03T04:00:00.000Z');
Basically my application deals with events and dates only, but moment.js converting the daylight savings time is causing issue with dates. Does it have any setting which will disable it across the entire application usage?
If you are saying that you want moment to display your date and time (which is UTC, as indicated by the 'Z'), exactly as is, you should use moment.utc:
moment.utc('2016-06-03T04:00:00.000Z').format()
"2016-06-03T04:00:00Z"
When you use the default moment constructor, as you are now, you are telling moment to convert your UTC time to local time, and this is why you are seeing a time difference. For instance, on my local machine (I am currently UTC-5) I get the following:
moment('2016-06-03T04:00:00.000Z').format()
"2016-06-02T23:00:00-05:00"
This question comes up quite a lot, so I wrote this blog post that explains moment's constructor functions and how it converts ISO8601 dates in detail: https://maggiepint.com/2016/05/14/moment-js-shows-the-wrong-date/
In my case, I had a problem with timezone changing due to 'daylight saving time'.
I had the next period:
{
"from": "2020-10-01 00:00:00 +0200",
"to":"2020-11-01 00:00:00 +0100",
}
And I wanted to get:
{
"from": "2020-10-01 00:00:00 +0200",
"to":"2020-11-01 00:00:00 +0200",
}
My solution is to get current (local) timezone and set it to the both date moment:
const currentTzOffset = moment().utcOffset(); // getting current timezone offset
const startToLocalZone = moment(from, yourDateFormat)
.local() // just checking. not sure if this is necessary
.utcOffset(currentTzOffset) // put your tz to here
.format(yourDateFormat);
const endToLocalZone = moment(to, yourDateFormat)
.local() // just checking. not sure if this is necessary
.utcOffset(currentTzOffset) // put your tz to here
.format(yourDateFormat);
console.log(startToLocalZone); // output: "2020-10-01 00:00:00 +0200"
console.log(endToLocalZone); // output: "2020-11-01 00:00:00 +0200"
And dont forget to set your date format instead 'yourDateFormat'
var tz = 'America/Vancouver'; // or whatever your time zone is
var dt = '2022-03-13T07:00:00.101Z'; // or whatever date/time you're working with
var momentVal = moment.tz(dt,tz)
function isNextDayDST(mObj){
return mObj.clone().add(1, 'days').isDST();
}
function isTodayDST(mObj) {
return mObj.clone().isDST();
}
function getDSTHourCompensation(mObj) {
const todayDST = isTodayDST(mObj.clone());
const tomorrowDST = isNextDayDST(mObj.clone());
if(todayDST == false && tomorrowDST == true) {
return 1
}
if(todayDST == true && tomorrowDST == false) {
return -1
}
return 0
}
function removeDST(mObj){
const hourCompentation = getDSTHourCompensation(mObj);
return mObj.clone().add(hourCompentation, 'hours');
}
console.log(momentVal.format('YYYY-MM-DD HH:mm'))
console.log(removeDST(momentVal).format('YYYY-MM-DD HH:mm'))
Maybe use the moment lib to compensate for the hours when you want to remove DST for the particular case.
Related
I've tried to look at some code examples for this but I'm stuck here. I have a json which is reading dates as strings. For example:
1/1/1993 is 33970.
I have points on a map, each with associated dates. I have a time-slider based on dates. Once the time slider is updated, I would like the appearance of the points to change based on the date value of slider.
// build slider
var inputValue = null;
var year = ["1993","1994","1995","1996","1997","1998","1999","2000","2001","2002","2003","2004","2005","2006","2007","2008","2009", "2010","2011","2012","2013","2014","2015","2016","2017","2018","2019"];
Build function to update slider.
function update(value) {
document.getElementById("range").innerHTML=year[value];
inputValue = year[value];
d3.selectAll(".points")
.attr("fill", dateMatch);
}
d3.select("#timeslide").on("input", function() {
update(+this.value);
console.log(value)
});
And finally, build the function that matches the date in my data, to the date in the time slider!
function dateMatch(data, value) {
var d = new Date(data.properties.Sign_Date);
var y = [d.getFullYear()];
console.log(y)
console.log(d)
if (inputValue == y) {
this.parentElement.appendChild(this);
return "blue";
} else {
return "#999";
};
}
I think the template here should work but there is an issue reading in the dates in the dateMatch function. For some reason, it's just printing
Wed Dec 31 1969 16:00:41 GMT-0800 (Pacific Standard Time)
For every record in my data. Which doesn't make sense since my data doesnt even go back to 1969. Can anyone tell me what they think might breaking here, or better, an easier way to filter this temporal data?
You need to convert all your dates to real dates. Be aware, if you don't use UTC (universal time zone) or another defined timezone the date conversion will depend on the timezone set on the computer. For more about javascript dates I suggest reading MDN.
function createDateUTC(yourDateFormat) {
var parsed = yourDateFormat.split('/'),
day = +parsed[0],
monthIndex = +parsed[1]-1,
year = +parsed[2]
return new Date(Date.UTC(year, monthIndex, day))
}
While trying to create date feeding a timeStamp to the Date() constructor (snippet below) - the first call works but the second call throws ('invalid date') error whenever a time zone is specified - how to correct this?
var date1 = new Date('Dec 17, 1995 03:24:00 AM EST'); //<---- THIS WORKS!!!
console.log(date1)
// Sun Dec 17 1995 03:24:00 GMT...
var date2 = new Date('1995-12-17T03:24:00 EST'); //<---- THIS DOES NOT WORK!!!
console.log(date2)
Output:
> Sun Dec 17 1995 13:54:00 GMT+0530 (India Standard Time)
> Invalid Date
> false
> NaN
This is not a duplication question as initialization from timeStamp fed to constructor is requested as against the suggested duplicate question.
You are providing the wrong format in the argument.
new Date('1995-12-17T03:24:00 EST');
What's wrong
The format you are provideing in date constructor is standard called as ISO_8601. According to standard you can not provide timezone offset like you did.
Correct way
If the time being described is one hour ahead of UTC (such as the time in Berlin during the winter), the zone designator would be "+01:00";
new Date('1995-12-17T03:24:00+01:00');
If the time being described is one hour behind of UTC, the zone designator would be "+01:00";
new Date('1995-12-17T03:24:00-01:00');
Following all refer to same time "18:30Z", "22:30+04", "1130−0700", and "15:00−03:30".
This code doesn't solve the problem for directly timestamping time-zones but provides an alternative to supporting preferred time-zones as well creating js acceptable time-stamps converting numerical month to month name dynamically. This is just crude solution open to suggestions.
function getTZId(zone) {
var retId = zone;
if (zone) {
//placeholder to maintain / add new zone id patterns
//a word of caution: some timezones are not supported so offset will be required
var zoneIds = {
'EST':[/ET/,/EST/,/EAST/,/OTT/],
'UTC+5:30':[/IST/,/IND/,/GURG/],
'CST':[/CENTR/,/NA/],
'UTC':[/UTC/,/GMT/,/ZULU/,/Z/,/GREEN/]
}
//default zone id
var defZnId = 'UTC';
var fnd = _.findIndex (
Object.keys( zoneIds ),
//lookup all zone id's for a match among respective zone patterns till first matching zone id is found
znId => {
return (
_.findIndex (
zoneIds[znId],
//match each zone pattern for this zone id till the first match is found
znPtrn=>{
return znPtrn.test( zone.toUpperCase() )
}
) !== -1
)
}
);
//return zone id if matching zone id found else return default zone id: 'UTC'
retId = (fnd!==-1?Object.keys( zoneIds )[fnd]:defZnId);
}
return retId;
}
var yr = "2018", mn = "2", dy = "28", hr = "14", min = "05";
var timezone = "EST";
//get date components for current timezone like month names etc
var tmpDt = (new Date(`${yr}-${mn}-${dy}T${hr}:${min}`)).toDateString().match(/^([A-Za-z]+)\s+([A-Za-z]+)\s+(\d+)\s+(\d+)$/i);
//use above code to create appropriate time stamp
return (new Date(`${tmpDt[2]} ${tmpDt[3]}, ${yr} ${hr}:${min}:00 ${getTZId(tmZoneStr)}`));
I am facing an issue in timezone. Right now I am saving time zone from client side and stored all DateTime in UTC. It's working properly but when I am trying to convert DateTime for UTC behind time zones like CST, EST, EDT it showing wrong data.
Issue -
Let's assume if I did any task at 10 PM EDT and it would be saved in DB as 2 AM(as per UTC) but when I am trying to fetch data for a day and passing current UTC date.
My question is If am trying to fetch data for a day like 11 midnight( from EST) to the current time, but my conversion from UTC to EST is wrong due to UTC 12midnight is yesterday's 8 PM(as EDT 4hr behind from UTC). (From Date[UTC convert to EDT] - 06/07/2017 08:00pm) and To Date - 06/07/2017 11:00 pm) Due to this conversion I am getting data from 8 pm to 11 pm only <- I am expecting from date is 06/07/2017 04:00 AM as per UTC.
Code -
Below is the code for conversion. In from date I have taken utcnow.date only and from a date
Javascript code -
function setTimezoneCookie() {
try {
var timezone_cookie = "timezoneoffset";
var timeZoneName = "timezonename"
var tz = jstz.determine();
var aa = tz.name();
// if the timezone cookie not exists create one.
if (!$.cookie(timezone_cookie)) {
// create a new cookie
$.cookie(timezone_cookie, new Date().getTimezoneOffset());
$.cookie(timeZoneName, aa);
}
else {
var storedOffset = parseInt($.cookie(timezone_cookie));
var currentOffset = new Date().getTimezoneOffset();
if (storedOffset !== currentOffset) {
$.cookie(timezone_cookie, new Date().getTimezoneOffset());
$.cookie(timeZoneName, aa);
location.reload();
}
else {
$.cookie(timeZoneName, aa);
}
}
}
c# code -
fromDate =Convert.ToDateTime(fromDate).ToClientTimeZoneinDateTime().ToString();
toDate = Convert.ToDateTime(toDate).ToClientTimeZoneinDateTime().ToString();
ObjectParameter totalRecords = new ObjectParameter("TotalRecords", typeof(int));
var DetailsList = objDetailsList.GetDetails(loginUserId,locationId, userId, taskType, pageIndex, numberOfRows, sortColumnName, sortOrderBy, textSearch, totalRecords, fromDate, toDate);
if (DetailsList.Count() > 0)
{
string output = BuildJQGridResults(DetailsList, numberOfRows, pageIndex, Convert.ToInt32(totalRecords.Value));
response.Write(output);
}
else
{
JQGridResults result = new JQGridResults();
List<JQGridRow> rows = new List<JQGridRow>();
result.rows = rows.ToArray();
result.page = 0;
result.total = 0;
result.records = 0;
response.Write(new JavaScriptSerializer().Serialize(result));
}
Below is the method of converting UTC time to client timezone
public static DateTime ToClientTimeZoneinDateTime(this DateTime dt)
{
try {
if (System.Web.HttpContext.Current.Request.Cookies["timezoneoffset"] != null || System.Web.HttpContext.Current.Request.Cookies["timezonename"] != null)
{
var timezonename = System.Web.HttpContext.Current.Request.Cookies["timezonename"].Value;
timezonename = timezonename.Replace("%2F", "/");
var timezoneLocal1 = FindTimezoneName(timezonename);
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(timezoneLocal1);
bool isCurrentlyDaylightSavings = tzi.IsDaylightSavingTime(dt);
if (isCurrentlyDaylightSavings == true)
dt.AddHours(1);
var timeOffSet = System.Web.HttpContext.Current.Request.Cookies["timezoneoffset"].Value;
var offset = int.Parse(timeOffSet.ToString());
dt = dt.AddMinutes(-1 * offset);
return dt;
}
return dt.ToLocalTime();
}
catch (Exception)
{
return DateTime.UtcNow;
}
}
No doubt as Timezone handled properly but facing an issue for behind timezone from UTC if end user trying to fetch data after 8 PM EDT. I have attached screenshot as well.
Below img of before conversion -
Above img of after conversion -
How do I need to handle this situation?
The main problem is that you're converting the wrong direction. You are converting from UTC to the user's time zone, but your input is in the user's time zone, so you need to convert the other direction - from the user's time zone to UTC. Then your query will show better results.
A few other things:
Don't convert time zones by trying to add/subtract minutes or hours manually. Use the conversion functions offered on TimeZoneInfo, such as ConvertTimeFromUtc, ConvertTimeToUtc, etc. There's no need to test for DST.
The try/catch shouldn't be in your code at all. Throw an exception if you can't perform the operation. Don't mask important errors by swallowing exceptions.
dt.ToLocalTime() shouldn't be in your code either. Never rely on the server's local time zone.
The offset returned by new Date().getTimezoneOffset() is the user's current offset. You cannot assume that it's the correct offset for the dates chosen. You don't that anyway, as you're already getting the time zone name. (You don't need the timezoneoffset cookie at all.)
The time zone name returned by jstz.determine() on the client-side is going to be an IANA tzdb identifier, such as America/Los_Angeles. These aren't going to work on the server-side with TimeZoneInfo.FindSystemTimeZoneById (unless you are running .NET Core on Linux or Mac). Conversion to a Windows time zone is required. I see you have a FindTimeZoneName function, which I assume is performing the conversion. You didn't show the details in your code, but I highly recommend you use my TimeZoneConverter library to implement that, as it's maintained with changes to time zones.
Reading cookies and time zone conversion are separate concerns. Don't bundle them together.
Ultimately, you should have something like this:
public static DateTime FromTimeZoneToUtc(this DateTime dt, string timeZone)
{
var windowsId = TimeZoneConverter.TZConvert.IanaToWindows(timeZone);
var tzi = TimeZoneInfo.FindSystemTimeZoneById(windowsId);
return TimeZoneInfo.ConvertTimeFromUtc(dt, tzi);
}
Or, even better, if you use Noda Time, then you don't need to convert time zones at all.
public static DateTime FromTimeZoneToUtc(this DateTime dt, string timeZone)
{
var tz = DateTimeZoneProviders.Tzdb[timeZone];
var local = LocalDateTime.FromDateTime(dt);
return local.InZoneLeniently(tz).ToDateTimeUtc();
}
When converting a UTC date format to timestamp this condition will always fail
const start_time = "2017-03-02T15:57:00Z";
const stop_time = "2017-03-02T17:51:00Z";
const local_timestamp = 1488498242256; // Thu Mar 02 2017 16:44:02 GMT-0700 (MST)
const start = moment(start_time).valueOf(); // 1488470220000
const stop = moment(stop_time).valueOf(); // 1488477060000
const is_between = local_timestamp >= start && local_timestamp <= stop; // false
So I tried this and still failed
const start = moment(start_time).utc().valueOf(); // 1488470220000
const stop = moment(stop_time).utc().valueOf(); // 1488477060000
const is_between = local_timestamp >= start && local_timestamp <= stop; // false
Same thing here
const now = moment(local_timestamp);
const isBetween = now.isBetween(start, stop); // false
Please help me understand this.
When converting a UTC date format to timestamp this condition will always fail
A timestamp is anything that represents a date or time, so "2017-03-02T15:57:00Z", "Thu Mar 02 2017 16:44:02 GMT-0700 (MST)" and 1488498242256 are all timestamps.
1488498242256 represents "2017-03-02T23:44:02.256Z" which is not between "2017-03-02T15:57:00Z" and "2017-03-02T17:51:00Z", so the expected result of your tests is false.
So I tried this and still failed
It's not failing, it's returning the expected result.
When you do, say:
new Date(1488498242256)
then a Date instance is created with a time value of 1488498242256, which represents "2017-03-02T23:44:02.256Z". When you write this to output that generates a string, usually Date.prototype.toString is called and a string is generated in what the browser developers have determined is a human friendly format.
Typically this means that the host system timezone offset is used to generate the string and you see something like:
"Thu Mar 02 2017 16:44:02 GMT-0700 (MST)"
On SO, the console seems to use toISOString instead of the default toString, e.g.
var date = new Date(1488498242256);
// Standard output for the host environment
console.log(date);
// Call Date.prototype.toString specifically
console.log(date.toString());
If start and end are UTC times, then use moment.utc(start_time) and moment.utc(stop_time)
But it doesn't seem logical to compare UTC dates against a local date. That is what it looks like you are attempting.
Probably and easy answer to this but I can't seem to find a way to get moment.js to return a UTC date time in milliseconds. Here is what I am doing:
var date = $("#txt-date").val(),
expires = moment.utc(date);
Any idea what I am doing wrong?
This is found in the documentation. With a library like moment, I urge you to read the entirety of the documentation. It's really important.
Assuming the input text is entered in terms of the users's local time:
var expires = moment(date).valueOf();
If the user is instructed actually enter a UTC date/time, then:
var expires = moment.utc(date).valueOf();
I use this method and it works. ValueOf does not work for me.
moment.utc(yourDate).format()
As of : moment.js version 2.24.0
let's say you have a local date input, this is the proper way to convert your dateTime or Time input to UTC :
var utcStart = new moment("09:00", "HH:mm").utc();
or in case you specify a date
var utcStart = new moment("2019-06-24T09:00", "YYYY-MM-DDTHH:mm").utc();
As you can see the result output will be returned in UTC :
//You can call the format() that will return your UTC date in a string
utcStart.format();
//Result : 2019-06-24T13:00:00
But if you do this as below, it will not convert to UTC :
var myTime = new moment.utc("09:00", "HH:mm");
You're only setting your input to utc time, it's as if your mentioning that myTime is in UTC, ....the output will be 9:00
This will be the answer:
moment.utc(moment(localdate)).format()
localdate = '2020-01-01 12:00:00'
moment(localdate)
//Moment<2020-01-01T12:00:00+08:00>
moment.utc(moment(localdate)).format()
//2020-01-01T04:00:00Z
moment.utc(date).format(...);
is the way to go, since
moment().utc(date).format(...);
does behave weird...
This worked for me. Others might find it useful.
let date = '2020-08-31T00:00:00Z'
moment.utc(moment(date).utc()).format() // returns 2020-08-30T22:00:00Z
If all else fails, just reinitialize with an inverse of your local offset.
var timestamp = new Date();
var inverseOffset = moment(timestamp).utcOffset() * -1;
timestamp = moment().utcOffset( inverseOffset );
timestamp.toISOString(); // This should give you the accurate UTC equivalent.
This moment.utc(stringDate, format).toDate() worked for me.
This moment.utc(date).toDate() not.
here, I'm passing the date object and converting it into UTC time.
$.fn.convertTimeToUTC = function (convertTime) {
if($(this).isObject(convertTime)) {
return moment.tz(convertTime.format("Y-MM-DD HH:mm:ss"), moment.tz.guess()).utc().format("Y-MM-DD HH:mm:ss");
}
};
// Returns if a value is an object
$.fn.isObject = function(value) {
return value && typeof value === 'object';
};
//you can call it as below
$(this).convertTimeToUTC(date);
Read this documentation of moment.js here.
See below example and output where I convert GMT time to local time (my zone is IST) and then I convert local time to GMT.
// convert GMT to local time
console.log('Server time:' + data[i].locationServerTime)
let serv_utc = moment.utc(data[i].locationServerTime, "YYYY-MM-DD HH:mm:ss").toDate();
console.log('serv_utc:' + serv_utc)
data[i].locationServerTime = moment(serv_utc,"YYYY-MM-DD HH:mm:ss").tz(self.zone_name).format("YYYY-MM-DD HH:mm:ss");
console.log('Converted to local time:' + data[i].locationServerTime)
// convert local time to GMT
console.log('local time:' + data[i].locationServerTime)
let serv_utc = moment(data[i].locationServerTime, "YYYY-MM-DD HH:mm:ss").toDate();
console.log('serv_utc:' + serv_utc)
data[i].locationServerTime = moment.utc(serv_utc,"YYYY-MM-DD HH:mm:ss").format("YYYY-MM-DD HH:mm:ss");
console.log('Converted to server time:' + data[i].locationServerTime)
Output is
Server time:2019-12-19 09:28:13
serv_utc:Thu Dec 19 2019 14:58:13 GMT+0530 (India Standard Time)
Converted to local time:2019-12-19 14:58:13
local time:2019-12-19 14:58:13
serv_utc:Thu Dec 19 2019 14:58:13 GMT+0530 (India Standard Time)
Converted to server time:2019-12-19 09:28:13
This worked for me:
const localtime = 1622516400000
moment(localtime).utc(true).format()
We can get 2 UTC date formats.
const date = '2021-07-20T18:30:00Z';
moment.utc(moment(date).utc()).format(); // 2021-07-19T18:30:00Z
moment.utc(moment(date).utc()).toISOString(); // 2021-07-20T18:30:00.000Z (Complete ISO-8601)
This works in my case.
Library: "moment": "^2.29.1",
moment().utc().format()
Don't you need something to compare and then retrieve the milliseconds?
For instance:
let enteredDate = $("#txt-date").val(); // get the date entered in the input
let expires = moment.utc(enteredDate); // convert it into UTC
With that you have the expiring date in UTC.
Now you can get the "right-now" date in UTC and compare:
var rightNowUTC = moment.utc(); // get this moment in UTC based on browser
let duration = moment.duration(rightNowUTC.diff(expires)); // get the diff
let remainingTimeInMls = duration.asMilliseconds();