I noticed something odd when trying to determine if a given datetimeoffset occurred on the beginning or end of a timezoneadjustment (daylight savings).
And I'm not sure if I'm going about this the wrong way or not.
Take the following code for example:
class Program
{
static void Main(string[] args)
{
// Note: this is done on a swedish computer.
int year = 2015;
DateTimeOffset dateTimeJustBeforeOffsetChanges = new DateTime(year, 10, 25, 1, 59, 59);
DateTimeOffset dateTimeRightWhenOffsetChanges = new DateTime(year, 10, 25, 2, 0, 0); // 2015-10-25 02:00:00. This is how we set our offset. We let the implicit conversion do all the work :)
var daylightSavings = TimeZone.CurrentTimeZone.GetDaylightChanges(year);
Console.WriteLine(dateTimeJustBeforeOffsetChanges); // Prints out 2015-10-25 01:59:59 +02:00
Console.WriteLine(dateTimeRightWhenOffsetChanges); // Prints out 2015-10-25 02:00:00 +01:00 This is the exact time when the datetimeoffset starts using offset +02 instead of +01
Console.WriteLine(daylightSavings.End.ToString()); // Prints out 2015-10-25 03:00:00
Console.ReadLine();
}
}
As you can see from the above code, the offset changes from +1 hour to +2 hours on October 25:th at 2 o'clock in the morning when using the implicit conversion from a datetime to a datetimeoffset. However, when analyzing the current daylightsavings with the GetDaylightChanges method whe are told that the change should occur at 3 o'clock on October 25:th.
In my head the offset should change to +2 at 3 o'clock, not 2 o'clock, or am I wrong?
PS: This code is run on a Swedish machine with Swedish timezonesettings.
Firstly, GetDaylightChanges is accurate - the clocks did go back in Sweden at 3am local time.
Secondly, that doesn't mean that you've shown a bug anywhere in the BCL. The problem is simply that 02:00:00 occurs twice - once before the clocks go back, and once after. In other words, it occurs at 2015-10-25 02:00:00 +02:00 and 2015-10-25 02:00:00 +01:00. How do you expect the implicit conversion to tell which one you meant? Both are valid results, and it happens to be picking the later one, although that behaviour is unfortunately unspecified, at least in both the implicit conversion documentation and the DateTimeOffset constructor documentation.
This sort of thing is why in my Noda Time library, when you map from a LocalDateTime to a ZonedDateTime (by applying a time zone) you have to say what you want to happen if the value is ambiguous or skipped - so in this case, you could choose for it to resolve to either the later or the earlier occurrence of 2015-10-25 02:00:00.
Basically this is something you should think about, and decide how you want your application to behave... then you should specify the behaviour you want, using whatever API you're using. That's easier in some APIs than in others :)
Related
Im trying to trasform a date to utc but moment return the same value i use.
for example
moment(date, 'YYYY-MM-DD HH:mm:ss').utc().format('YYYY-MM-DD HH:mm:ss')
if i use date = '2022-01-07 11:30:00' moment return 2022-01-07 11:30:00
do i have to set the timezone of the value first? why moment return the wrong value? it should return +3 hours that date.
You'll need to define the timezone in which the date is, then the offset will be as expected:
Example, using Europe/Amsterdam as timezone
const date = '2022-01-07 11:30:00';
const utc = moment(date, 'YYYY-MM-DD HH:mm:ss')
.tz('Europe/Amsterdam')
.utc()
.format('YYYY-MM-DD HH:mm:ss');
console.log(utc);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.32/moment-timezone-with-data.min.js"></script>
This will output 2022-01-07 10:30:00 since Amsterdam time is -1 compared to UTC.
Small side node, quoting MomentJS Project Status page
We now generally consider Moment to be a legacy project in maintenance mode. It is not dead, but it is indeed done.
In practice, this means:
We will not be adding new features or capabilities.
We will not be changing Moment's API to be immutable.
We will not be addressing tree shaking or bundle size issues.
We will not be making any major changes (no version 3).
We may choose to not fix bugs or behavioral quirks, especially if they are long-standing known issues.
The data you pass in doesn't have any indication of the timezone it's in, so moment is (I believe) assuming it's in utc already.
In related news, look into using the date-fns library instead of moment. Moment is getting old...
Moment github
Moment.js is a legacy project, now in maintenance mode. In most cases,
you should choose a different library.
This returns the same date since you never indicated any timezone
var time = moment("2013-08-26 16:55:00") //this creates time in my tz
You can set a timezone like this:
var time = moment("2013-08-26 16:55:00").tz("America/Los_Angeles");
So Im using Fullcalendar and on dayClick I'm trying to find events that match the day clicked.
var events = $calendar.fullCalendar('clientEvents');
if(events.length > 0) {
for (var i = 0; i < events.length; i++) {
if (date.format('YYYY-MM-DD') == events[i].start.format('YYYY-MM-DD')) {
...
Now
date.format('YYYY-MM-DD')
returns the day I clicked but when the for loop gets to that days events then
events[i].start.format('YYYY-MM-DD')
returns the next day. This seems to be affected by UTC but this applies to ALL days with events. Not just today. I've tried different formats and still the same. Here's something I noticed though:
n
_ambigTime:false
_ambigZone:true
_d:Thu Feb 09 2017 08:00:00 GMT-0500 (EST)
_f:"YYYY-MM-DD HH:mm:ss"
_fullCalendar:true
_i:"2017-02-08 13:00:00"
_isAMomentObject:true
_isUTC:true
_isValid:true
_locale:f
Notice that _d and _i are different. _i is actually the right date/time. So how can I reference that?
All moment properties starting with _ (like _d and _i) are for internal use and should not be used.
If you want to check if two moment object represent the same day you can use isSame passing the second parameter to limit granularity, instead of comparing formatted strings. In your case:
date.isSame(events[i].start, 'day')
The problem is that some of your objects are created in UTC mode (_isUTC: true), so they will be displayed using UTC time (previous day in some cases) instead of local time.
More info about UTC mode here:
By default, moment parses and displays in local time.
If you want to parse or display a moment in UTC, you can use moment.utc() instead of moment().
This brings us to an interesting feature of Moment.js. UTC mode.
While in UTC mode, all display methods will display in UTC time instead of local time.
I am using Moment.js and manipulating a date using moment.hour(xx) moment.minute(xx).
When i console.log the moment i see that the object contains a _d and _i:
the _d contains the correct changed moment.hour() or moment.minute() changes however the _i object contains the original?
k {_isAMomentObject: true, _i: Thu Dec 11 2014 20:34:00 GMT+0200 (South Africa Standard Time), _isUTC: false, _pf: Object, _locale: j…}
_d: Thu Dec 11 2014 14:00:00 GMT+0200
_i: Thu Dec 11 2014 20:34:00 GMT+0200
Could anyone enlighten me?
Pay no attention to those. Use the various output functions, such as .format() instead. See the Moment.js guidance on this topic. In short, all fields that are prefixed with an underscore (_) should be considered off limits.
The moment internals have some quirks due to how the Date object works. All of the functions in the public API take them into account, but you probably don't want to figure them out yourself.
Just to be complete though, I'll elaborate on their purpose:
_i is the input used when create the moment object. It can be a string, a number, an array, or a Date object.
However, if another moment object is passed in, the _i will be copied to that moments _i, and other properties will also be copied over. _i will never be a moment object.
_i can also be undefined, in the case of creating the current moment with moment().
_d is the instance of the Date object that backs the moment object.
If you are in "local mode", then _d will have the same local date and time as the moment object exhibits with the public API. The timestamps returned by getTime or valueOf will also match.
If you are in "UTC mode", then _d will still have the same UTC date and time as the moment object exhibits with the public API. This may be confusing, as you'd need to look at getUTCDate and other UTC-based functions on _d in order to see them match. The timestamps will still match here as well.
If you've changed the time zone offset, with the utcOffset, zone, or tz functions, then the _d value cannot stand alone. It must also consider if _offset is defined. If it is, then the timestamp backing the _d object has to first be adjusted by the amount of the offset. You can see this behavior in the implementation of the valueOf method here.
Also, if you look at the string output of _d when a different offset or time zone has been applied, it will appear that _d is using the local time zone. However, that conversion to local time is simply a side effect of the toString function of the Date object. Moment does not use that result in its functions.
This is the behavior for these two fields as of the current version (2.10.6 as I'm writing this). However, there are other fields as well, and since these are internal fields, it's entirely possible the behavior could change in a future version. In particular, see issue #2616.
As a complement to #Matt's answer:
Checkout this result from the chrome's console:
date1 is a moment's valid object:
As you can see, ._d and ._i have different values. So you better use the format() function (as #Matt Johnson wrote) inside your source code.
I am creating a new Entity and inside constructor I set the datetime like
function Project() {
this.created = moment().format();
}
which produce a result in console the current date and time
Sat Jun 07 2014 18:48:41 GMT+0500 (Pakistan Standard Time)
As soon as I call save changes and see the posted date in the network tabe it changes the hour part of datetime 2014-06-07T13:48:41.000Z
It looks like Breeze does this, may be I am wrong, Any suggestion how can I prevent this to happen?
Breeze is just serializing the date for transport It is not transformed at all. If you look it is 5 hours different in UTC meaning it will localize out the same when you moment.format it again.
If you want to re-localize it just use moment(yourDate).format(LL) or something similar.
http://momentjs.com/ and go to Internationalization section
How to convert date and time to CDT time Zone in flex4
Regards,
Sushma
The Date object in Flash is always set to the computer's time settings. If the computer is already in the CDT timezone, then just getting any property from the object will be good. However, if you want to do a timezone 'conversion' into a timezone that the computer is not set to, you can get the UTC time and offset it like this:
var date:Date = new Date();
var timezone:int = -5;
date.hours = date.hoursUTC + timezone;
However, you're trying to get the actual CDT time, which only works during the summer in certain areas. For this, it's impossible for Flash to know exactly when that is UNLESS you code the exceptions (ie. if between this date and that date, do -6, else do -5) and you also need to know the actual location of the user (which is impossible through Flash unless the user gives you that info).
Can I ask why you need to know such a thing?