We are writing a c# server to generating the .ics files which would be shared by people from different timezones. We have one requirement says if the people in Sydney open the file the event says 9:30pm. The people in Perth should also see it as 9:30pm. i.e. No auto timezone offset applied the calendar by outlook.
I have looked many places and yet to find a solution.
Is that possible?
I don't think this really makes sense in terms of what an ics file represents - it's an invitation to an event, where "an event" is a thing which happens at a specific time. If something's happening at 09:30 in Sydney, then it's not happening at 09:30 in Perth so it can't be the same event. Sounds to me like you need to create multiple events, one for each timezone.
Related
My app works with a public calendar via CalDAV protocol (let's call it CalDAV calendar) which returns events in iCalendar format. One user started to create events in that calendar using Outlook localized to Russian language. It happened that Outlook put TZID field in the CalDAV calendar event in Russian language, as follows:
BEGIN:VCALENDAR
PRODID: some prod id
VERSION:2.0
BEGIN:VTIMEZONE
TZID:(UTC+03:00) Москва\, Санкт-Петербург
BEGIN:STANDARD
DTSTART:19710101T000000
TZOFFSETFROM:+0300
TZOFFSETTO:+0300
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
ORGANIZER;CN=UserName:MAILTO:username#mail.com
RRULE:FREQ=DAILY;UNTIL=20230108T100000Z
DTSTAMP:20230109T101100Z
UID:russiantz001
SEQUENCE:0
SUMMARY:Тест с 6 по 8 в 13 00 - 13 30
DTSTART;TZID="(UTC+03:00) Москва, Санкт-Петербург":20230106T130000
DTEND;TZID="(UTC+03:00) Москва, Санкт-Петербург":20230106T133000
DESCRIPTION:Russian TZ
CalDAV calendar treats events correctly. To deserialize iCalendar event I am using iCal.NET library which in turn uses NodaTime method DateTimeZoneProviders.Tzdb.GetZoneOrNull(TimeZoneId) to convert time from a time zone to UTC. It searches all time zone providers (IANA, BCL, serialization, etc) to see if TimeZoneId matches. Unfortunately, NodaTime does not understand TimeZoneId in Russian.
My question: how to get a correct English equivalent of the TimeZoneId in Russian generated by the localized Outlook?
.NET method FindSystemTimeZoneById throws exception that TimeZoneId is not found.
My app works in Linux environment. Therefore I cannot use Windows registry HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zones records. Moreover, to use registry records Windows should have been localized to the Russian language which would not happen for sure.
For now I am thinking just to use (UTC+03:00) prefix of the time zone Id in Russian, but I am not sure if this is right decision. For example, will time zone offset be correct during daylight saving period?
I would greatly appreciate any link or hint how to solve this conversion issue.
Time zone IDs should never be localized. What you have in the TZID field appears to be a time zone display name, not an ID. The application that created that file is incorrectly using the DisplayName property of the TimeZoneInfo object where it should be using Id property instead.
The correct Windows ID that should be showing in the file is "Russian Standard Time". Or it could (preferably) show the equivalent IANA time zone ID, which is "Europe/Moscow". They should be those exact strings and not translated to Russian.
The iCal format itself (and anything consuming it) doesn't care about this because it is strictly looking at the TZID field as it exists within the file. But anything else you use it for absolutely will.
The original application needs to be updated to return a time zone identifier instead of a display name in the TZID field.
Just using the time zone offset might be sufficient - but it may not always be. For example, if the time zone is one that changes offsets due to daylight saving time, the offset in the display name won't necessarily be the correct offset in effect for the event in the calendar.
The offset might also be different on the start time than on the end time, if the event crosses a DST transition. Moreover, if the event is recurring, the offset can be different between occurrences of events.
Then again, that particular time zone doesn't use DST (at least it doesn't presently), so you may never encounter such cases.
Short Version
I am attempting to access the TimeZoneStruct using VSTO from an Outlook Appointment.
The following error is thrown when attempting to access it.
System.Runtime.InteropServices.COMException (0x80040102): Object does not support property "http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/82330102".
Interestingly, I am able to get a similar property, TimeZoneDescription, using the same method with no exceptions:
http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/8234001F
My code is below; the first call to GetProperty succeeds, but the second does not.
//OK returns TimeZone Description string
dynamic tz1 = pa.GetProperty("http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/8234001F");
//NOK throws a COMException
dynamic tzStruct = pa.GetProperty("http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/82330102");
Long Version
I am developing a plugin that reads the Outlook calendar.
Currently the difficulty is with recurring appointments that were created with different timezones that have different Daylight Savings Time settings.
In order to find all appointments of a recurring meeting series, I need timezone information.
The first approach I used was to obtain the timezone information by extracting the timezone name. This works in most cases but is not ideal.
Outlook.PropertyAccessor pa = appointment.PropertyAccessor;
dynamic tz1 = pa.GetProperty("http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/8234001F");
This returns a string similar to (UTC+01:00) Amsterdam, Berlijn, Bern, Rome, Stockholm, Wenen.
This works correctly, but appointments that were sent from PC's with different languages, or in the case of "old" meetings with "obsolete" timezones that were deleted in a Windows Update, this does not work so well.
I will get meetings from computers from other languages, for instance this timezone is in French and my computer will not find it.
(UTC+03:00) Moscou, Saint-Pétersbourg, Volgograd
There are also updates; this timezone below no longer exists. Volograd was put in its own timezone at UTC+04:00 in 2016. See link from Microsoft.
Old: (UTC+03:00) Moscow, St. Petersburg, Volgograd
New: (UTC+03:00) Moscow, St. Petersburg
Obviously, matching the timezone name is never going to work.
I am focusing on getting the full information using the TimeZoneStruct instead; which should allow me to create a custom TimeZoneInfo Object; and then later I will be able to convert it into Local Time.
My problem is that when attempting to access this struct, I am getting the following error:
System.Runtime.InteropServices.COMException (0x80040102): Object does not support property "http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/82330102".
I have looked at OutlookSpy and can see that the property is indeed accessible.
I am using .NET Framework 4.6; Outlook 2016; Visual Studio 2015; Windows 8.1.
Any suggestions?
UPDATE
I'm trying to access this property using VBscript on Outlook Spy and getting a similar error.
The properties that are not PT_BINARY seem to work, for some reason.
Any ideas?
here's how to repeat the experiment
Using OutlookSpy, select a recurring appointment.
Make sure you are selecting the master and open the "Current Item" to run a script on the current AppointmentItem.
Enter the following code.
See screenshot for reference.
set msg = AppointmentItem
set pa = msg.PropertyAccessor
debug.print pa.GetProperty("http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/8234001F")
debug.print pa.GetProperty("http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/82310003")
debug.print pa.GetProperty("http://schemas.microsoft.com/mapi/id/{00062002-0000-0000-C000-000000000046}/82330102")
Outlook likes to play the Big Brother to prevent you from modifying, or sometimes even accessing, some properties that it considers special.
Using Extended MAPI (C++ or Delphi) or Redemption (any language, I am its author) instead of OOM is the only workaround.
I am currently working on a very simple C# add-in for Outlook that will iterate specific folders and output specific details about messages to a CSV file. I have that part complete, however I was wondering if there is a way to tell when a message is first modified or read? I know that I can see the last modified time, but I am hoping that I am just missing something in the API that those more experienced than me know of.
No, there is no way to do that. the best you can do is read the PR_LAST_VERB_EXECUTED MAPI property (DASL name "http://schemas.microsoft.com/mapi/proptag/0x10810003") - it will tell the time last time the message was replied to or forwarded.
I'm trying to make a system that basically allows me to shove a DLL in an installation and some code in an exe that allows me to release all of my future programs as beta releases for a while.
Now the problem is of course if I'd want to do that, i'd need to choose until when the program is valid. Which is fine, except that by changing your system clock, you can easily bypass the system.
Now, I'd like to hear what people generally do for something like this.
I've been trying a few approaches such as contacting a site to give the timestamp and compare that, which would be fine if it didn't always increase the program start time by over 9000
and and the fact that people would then not be able to use it if they're not connected to the internet.
Any suggestions are much appreciated.
This is not 100% guaranteed solution but it will take you there
You will need to implement these things in the config file (Why Config file, because if user deletes it your app won't run). Also encrypt all the following data.
Store the Date and Time on which application ran.
Store the exact amount of time for which application ran.
By doing so you can avoid:
If user change the computer time, you will come to know that, as your app is logging Date and Time, it might overlap the earlier time, say user ran app on 6th and 10th of month, and then he reverts date to 7th, you will come to know about it.
Secondly user can change the date on every run to single date, in that case the total duration used will help you. Say user set date to 1st of month every time he runs it, in that case, he can use app for 24 Hrs only not more than that.
Other options like
Checking time from External Server (Flaw: Requires internet access)
Storing Time in Registry (Flaw: User can easily manipulate registry)
Hope this helps you.
If your software can access some network share on some local server/nas, you can create a new file on this network share, and this file will have a creation time set using the clock of the server/nas, so you can compare the time set on the server/nas to the time of the local computer.
Or you can also save somewhere (a file, in the registry, in a DB) the last time of the last execution, and if the clock go back in time, then you can lock the application and require further assistance :-)
I am creating a simple application that will allow users to download .ICS files, and import them into their chosen calendar application/site.
I am happy with the creation process, but have a question regarding opening them in outlook.
(will be developed in C#, ASP.NET)
When I open one, it adds a new calendar, and doesn't add the events to the existing calendar.
Is it possible to open, and add to the existing calendar?
Example from a generate ICS file below (test data obviously)
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
DTSTART:20100623T1101100Z
DTEND:20100623T1401400Z
SUMMARY: England v Slovenia
LOCATION: Some where in South Africa
END:VEVENT
BEGIN:VEVENT
DTSTART:20100624T1101100Z
DTEND:20100624T1401400Z
SUMMARY: England v Slovenia again (replay)
LOCATION: Some where in South Africa
END:VEVENT
END:VCALENDAR
Yes, but that has to happen by the user and not the ICS file; I remember dealing with this before too, if you want to import into an existing calendar, there is an import feature in the menu...
Sorry for the vagueness, I dealt with that long ago and cannot remember the exact steps... I did find the answer in the help I believe, but essentially you can import them in, but if you open up the ICS directly, it creates a new calendar.
Also, it isn't smart enough to delete the old ones, so if you import more than once, you will have duplicates.
HTH.
To add events to an existing calendar, first you have to save .ics file and then import it, choosing Import instead of New while importing.