Google Calendar API v3 time zone issues - google-calendar-api

Using .Net API wrapper for Google Calendar API.
First get primary calendar id
Get timezone of primary calendar (returns good data, e.g., "America/Los_Angeles")
Create a calendar event. Set start time and end time. Set timezone.
Dim eStart As New EventDateTime
eStart.DateTime = _startAt
eStart.TimeZone = GoogleTimeZone
Dim eEnd As New EventDateTime
eEnd.DateTime = _endAt
entry.Start = eStart
entry.End = eEnd
eEnd.TimeZone = GoogleTimeZone
CalService.Events.Insert(entry, calendarid).Execute()
But the events are being created at 3am when the start time specified is 11am.
Google API documentation states "A time zone offset is required unless a time zone is explicitly specified in timeZone" and for timezone "The time zone in which the time is specified. (Formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich".)".
Timezone value is being specified properly.
Basically, it is not making any difference whether or not timezone is specified. Event is created in GMT in google calendar.
What is wrong here?

Fixed it (or let's just say hacked it). Google .Net API wrappers are absolutely crap (and this goes to wrapper of all of their APIs and not just Calendar API).
The issue was that event.Start and event.End automatically converts dates and add a "Z" at the end. This tells Google that the date is in GMT format. There is no reason for putting a "Z" because even without it, Google considers GMT. So basically, event.TimeZone=value was being disregarded because the time was appended by "Z".
After I removed the "Z", everything worked ok.
entry.Start.DateTimeRaw = replace(entry.Start.DateTimeRaw,"Z","")
entry.End.DateTimeRaw = replace(entry.End.DateTimeRaw,"Z","")

I fixed it by creating an instance of a DateTime object that uses the DateTimeKind enum as one of the constructors. I found the default DateTime.Kind property value is DateTimeKind.Utc when deserializing a JSON date. That's why a Z (UTC) value is in the Raw for me. The time zone value will be correct when DateTimeKind.Local is applied to the DateTimeKind argument in one of the constructors that takes it.
DateTime dt = new DateTime(oldDateTime.Ticks, DateTimeKind.Local);
DateTime dt = new DateTime(yearVar, monthVar, dayVar, hourVar, minuteVar, secondVar, DateTimeKind.Local);

Instead of setting the Datetime property that is part of the Start and End objects, you should give the DateTimeRaw a value and assign a timezone to it like this:
eventItem.Start = new EventDateTime()
{
DateTimeRaw = input.Start.ToString("yyyy-MM-ddTHH:mm:ss"),
TimeZone = "America/New_York"
};
Noticed that I'm not adding a Z or any timezone representation at the end of the string format. That should fix the issue and should prevent google from ignoring the timezone property when you've set a value.
In addition, if you hover over the DateTime property of the Start or End object in Visual Studio, it is described as the following: DateTime representation of EventDateTime.DateTimeRaw(see image).
Which in this case, replacing the Z value for an empty string will only make the problem worst because your DateTime property will also be updated. I hope this is helpful to anyone in the future.

Related

Moment return the same value passed to it instead of utc value

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");

adding current time to ambiguous date using momentjs

I'm currently using FullCalendar and need to add the current time to an ambiguous date moment in the select callback function.
When selecting a day in month view, the callback function parameters "start" and "end" return an ambiguous date (no time) moment. I'm using the following to add the current time to the date then convert it back to a moment but wonder if this is the proper way to do it...
if(!start.hasTime()){
start = moment(start.format('YYYY-MM-DD'+' '+ moment().format('HH:mm:ss')));
end = moment( end.format('YYYY-MM-DD'+' '+ moment().format('HH:mm:ss')));
}
As you can see, I'm converting the "start" and "end" dates and current time moments into strings then converting the concatenated string back into a moment.
I want to make sure that the moment i'm creating is in valid ISO 8601 format.
Thanks,
Any help would be appreciated.
In the official docs says if you call format() function you get the date in ISO 8601 format.
check this out: jsfiddle
Furthermore, if you dont want to handle the timezones, you can use the utc() method
I had the same issue, strangely when I upgraded to fullcalendar v3.40. According to fullcalendar docs,
the format() and toISOString functions have been overridden within fullcalendar for ambiguously timed moments to return dates only i.e. '2017-03-06'. To overcome this and set a time, you need to create a new moment object which is what you have done. To ensure consistent parsing across browsers though, you should specify the format you are parsing as recommended by moment docs. So for your scenario, it will be:
if(!start.hasTime()){
var format = 'YYYY-MM-DD HH:mm:ss';
start = moment(start.format('YYYY-MM-DD'+' '+ moment().format('HH:mm:ss')), format);
end = moment( end.format('YYYY-MM-DD'+' '+ moment().format('HH:mm:ss')), format);
}
To make the code cleaner and easily readable though, you could create a new moment using the unix timestamp (which is a number and doesn't rely on string formats) of the start moment and set the time using the moment set function. So it could now look like this:
if(!start.hasTime()){
var timestamp = start.valueOf();
var now = moment();
var startMomentWithNowTime = moment(timestamp).set({
'hour': now.hour(),
'minute': now.minute(),
'second': now.second()
});
start = startMomentWithNowTime;
end = startMomentWithNowTime;
}
Excuse the descriptive variable naming startMomentWithNowTime. A few more lines but hopefully easier to read. You could also wrap this logic in a function to use on demand. Hope it helps!

System.DateTime comparison ('>') or ('<') does not give what I expected

I want to get files from a list for all the files whose filedate > today's cutOff - so, I have the following codelet
string[] MyFiles = Directory.GetFiles(MyConfig.pathTransmittedFiles, "*.adf")
.Where(file => new FileInfo(file).LastWriteTime > dtCutOff).ToArray();
I have a file whose LastWriteTime is "{11/3/2015 1:33:26 PM}" being picked up by my collection with dtCutOff == "{11/3/2015 1:33:26 PM}"! So '>' didn't seem to work.
First, I would try running it without the Where clause, just to make sure that all files you expect are indeed part of the initial array returned from Directory.GetFiles. It's entirely possible that date/time comparison is not the source of the discrepancy. It may be more related to the issue Ivan linked to in the question comments, or it may be permission related, or some other thing.
Next, be aware that DateTime violates SRP in that it has a Kind property, which is one of the three DateTimeKind enumeration values. It's either Local, Utc, or Unspecified.
In the case of DateTime.Now, the Kind will be DateTimeKind.Local. File.GetLastWriteTime also returns its value with local kind. Therfore, if you always derive your dtCutOff from DateTime.Now in the manner you showed in the question, then it will almost always be the correct comparison function.
The "almost" stems from the fact that DateTimeKind.Local can actually represent two different kinds under the covers. In other words, there are actually four kinds, but two of them are exposed by one. This is described as "DateTime's Deep Dark Secret" in Jon Skeet's blog post More Fun with DateTime, and is also mentioned in the comments in the .NET Framework Reference Source. In practice, you should only encounter this in the ambiguous hour during a fall-back daylight saving time transition (such as just occurred last Sunday 2015-11-01 in the US).
Now, to the more likely case that your dtCutOff is actually derived not from DateTime.Now, but rather from user input or database lookup or some other mechanism, then its possible that it actually represents the local time in some other time zone than the one on your local computer. In other words, if the dtCutOff has a Kind of DateTimeKind.Utc, then the value is in terms of UTC. If it has a Kind of DateTimeKind.Unspecified, then the value might be in terms of UTC, or the local time zone, or some other time zone entirely.
Here's the kicker: Comparison of two DateTime values only evaluates the value underlying the Ticks property. It does not consider Kind.
Since file times are absolute points in universal time (on NTFS anyway), then you really should use the File.GetLastWriteTimeUtc method, rather than the methods that work in local time.
There are two approaches you could use:
Load the modified property as UTC, using:
myResult.modified = File.GetLastWriteTimeUtc(myFile);
Populate dtOffset appropriately.
If you're loading from the current time, then use DateTime.UtcNow.
If you're loading from other input, ensure the value is converted to UTC to match the input scenario. For example, use .ToUniversalTime() if the value is in terms of the local time zone, or use the conversion functions in the TimeZoneInfo class if the value is in another time zone.
OR
Change your modified property to be a DateTimeOffset instead of a DateTime.
Load that using:
myResult.modified = new DateTimeOffset(File.GetLastWriteTimeUtc(myFile));
Define dtCutOff as a DateTimeOffset, and populate appropriately.
If you're loading from the current time, then use DateTimeOffset.UtcNow.
If you're loading from other input, ensure the offset is set to match the input scenario. Use TimeZoneInfo functions if you need to convert from another time zone.
DateTimeOffset has many advantages over DateTime, such as not violating SRP. It's always representing an absolute moment in time. In this scenario, it helps to know that comparison operators on DateTimeOffset always reflect that absolute moment. (In other words, it internally adjusts to UTC before doing the comparison.)
This code works:
var cutffDate = new DateTime(2015,1,1); // or whatever
var allFiles = Directory.GetFiles(MyConfig.pathTransmittedFiles, "*.adf");
var datedFiles = allFiles.Where(f => (new FileInfo(f)).LastWriteTime > cutffDate);
Update:
Since your issue seems to be a precision-related one you could change the comparison to:
const long precision = 10; // vary this as needed
allFiles.Where(f =>
(new FileInfo(f)).LastWriteTime.ToFileTime()/precision > cutffDate.ToFileTime()/precision);
Alternatively you could use ...LastAccessTime.Ticks/TimeSpan.TicksPerMillisecond
In addition to that you may need to convert all DateTime values to UTC (LastAccessTimeUtc and DateTime.UtcNow) to make sure it's not some weird timezone issue
Since the files were fed into the queue once a day so the scale of precision is not required down to a millisecond or something. So that one-second TimeSpan difference is acceptable to do the trick and make my case work.
string[] MyFiles = Directory.GetFiles(MyConfig.pathTransmittedFiles, "*.adf")
.Where(file => new FileInfo(file).LastWriteTime - TimeSpan.FromSeconds(1) > dtCutOff)
.ToArray();
Now my file with modified date "{11/3/2015 1:33:26 PM}" didn't go into my collection when my cutOffDate is "{11/3/2015 1:33:26 PM}" while my other file with modified date "{11/3/2015 1:33:27 PM}" have successfully passed into my collection as expected!! So, it works and that's how it should work after all these advises! Thanks ye-all.
Looks like your Where clause lambda might be incorrect. Try this.
string[] MyFiles = Directory.GetFiles(MyConfig.pathTransmittedFiles, "*.adf").Where(file => file.modified > dtCutOff).ToArray();

events (as a json feed), start end parameters unix timestamp, are different if I change my OS time zone

I'm using the fullcalendar plugin and would appreciate if someone can give me a hand.
I am getting json events through a PHP URL.
something like this:
$('#calendar').fullCalendar({ events: "/myfeed.php" });
So in my php page that returns the events, I am getting 3 GET parameters:
'_'
'start'
'end'
The start and end parameter, indicate the date in UNIX timestamp.
So far so good, the problem that occurs is that if I change the time zone on my OS. also change these parameters start and end, for the same query in the same day in the calendar.
the weirdest part is that it only happens in Mozilla Firefox.
in Google Chrome, this problem does not occur.
e.g.
I have set my time zone ((UTC-04: 00) Santiago)
I'm referring to the day 09.09.2012 on the agenda,
firebug shows me that these parameters are being sent to my php page
_ 1347245953581
end 1347246000
start 1347159600
but if I change the time zone from my OS to ((UTC-03: 00) Buenos Aires)
consulting on 09.09.2012 on the agenda,
are other parameters which are now sent to the PHP page.
_ 1347246338047
end 1347332400
start 1347246000
Being that it is the same day, are other start and end parameters which are sent to check for events.
There is an ignoreTimezone option on the fullcalendar that might help. I'm not sure if it affects the start/end time passed to the feeds.
http://arshaw.com/fullcalendar/docs/event_data/ignoreTimezone/
Another option is to convert the passed timestamp to a Date object and get the local data from the Date object afterwards and use that in your queries.
Convert a Unix timestamp to time in JavaScript
I know it is not the exact answer, but it might help you out a bit.
Here is a sample piece of PHP code to convert the passed timestamp into a local formatted date:
$startts = $_REQUEST["start"]; // original timestamp
$startdt = new DateTime('now', new DateTimeZone('Europe/Oslo') ); // setup a local datetime
$startdt->setTimestamp($startts); // Set the date based on timestamp
echo $startdt->format('Y-m-d H:i:s'); // Output local date and time

Flex- Time Zone Conversion

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?

Resources