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.
Related
I am search Outlook using interop and I'm trying to filter emails based on date & time, including down to milliseconds, but it appears not to be supported.
I have the following filter, if I remove the sub-second component it works - it does not return anything, but with the '.1234' it is returning everything in the Inbox.
urn:schemas:httpmail:datereceived > '2023-01-09 13:22:22.1234' and urn:schemas:mailheader:subject like '%Example Test Email'
Is it possble to filter/search using sub-second values?
Is it possble to filter/search using sub-second values?
Nope. Outlook evaluates date-time values according to the time format, short date format, and long date format settings in the Regional and Language Options applet in the Windows Control Panel. In particular, Outlook evaluates time according to that specified time format without seconds. If you specify seconds in the date-time comparison string, the filter will not operate as expected.
Yes, both Outlook UI and OOM go though the same code that always rounds all datetime values to minutes. You'd need to use Extended MAPI (C++ or Delphi) or Redemption (any language, I am its author) if you want to work around that limitation.
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 need to set my system's time zone automatically using location. when I travel to some other places my system time zone will remains same.When I open my WPF Application and if the internet is connected, is it possible to automatically set the time zone of my system by getting the current time zone by location?
You would need to
Have a reliable source of location information.
Pass the coordinates determined in step 1 to one of these techniques to get an IANA time zone.
Translate the IANA time zone to a Windows time zone using CLDR mappings, as described here.
Set the Windows time zone using one of the approaches from this answer.
Explain to your users why your application is doing something that is really their own responsibility (or the operating system's responsibility). In other words, don't be sneaky about this. If you're going to do it, it should be a prominent feature of your application, and you should have the user's confirmation before changing anything. Remember, the time zone setting is global for the machine, not just for your application.
IMHO, if this isn't a system utility you're writing, then you should just use the determined time zone instead of trying to set the system to it.
Step one: you need to get the users location I suggest HostIP
Step two: get the time zone of that location Google maps time zone API
then you have to stitch those together.
I'm making a Notepad program with Windows Form and having a problem with the Date/Time feature:
My system time and date format (short) are hh:mm tt M/d/yyyy. When I press F5 (Date/Time feature) in Notepad, it add a time string with format like above. Then I change the system time and date format to HH:mm dd-MMM-YY and press F5 again in Notepad, it add another time string with the format I've changed.
But with my Notepad project (I use DateTime.Now.ToShortTimeString() and DateTime.Now.ToShortDateString() to do this feature), I have to start the program again if I want the format to take effect in my program, otherwise it will use the first format no matter how many times I press F5.
So I want to ask if there is a way to fix this.
I'm using VS 2013.
Very good question. The date is formatted according to current user culture information, but the information is cached by .NET. What you need to do is force .NET to clear the cache by calling CultureInfo.ClearCachedData method beforehand.
More information here: https://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.clearcacheddata(v=vs.80).aspx
Please also note, that clearing the cache every time a user wants to insert Date & Time is somehow missing the point of caching (OK, I am exaggerating a little bit). What you can do is only clear the cache, when the system tells you that its configuration has changed. You do this by listening to SystemEvents.UserPreferenceChanged event. More information in answer here: How to receive event when user changes system's culture
See SystemEvents class, UserPreferenceChang* events.
Please read this question fully and carefully before answering. The answer is not as simple as it might appear.
I am writing a program that needs to keep track of the modified datetime of files, some of which are stored on an external FAT32 drive. The program is being run on various Windows 7 machines.
The problem is the UTC modified datetime changes when the current UTC offset changes. Specifically, when we go from New Zealand Standard Time (UTC+12) to New Zealand Daylight Time (UTC+13) and back again. That is not a typo - the UTC modified datetime changes. It shouldn't, that is kind of the point of UTC, but it does. This appears to be a limitation of the FAT32 file system - files on NTFS work fine.
Console.WriteLine(DateTime.Now.ToString() + (DateTime.Now.IsDaylightSavingTime() ? " Daylight" : " Standard"));
Console.WriteLine(new FileInfo(args[0]).LastWriteTimeUtc.ToString("yyyyMMdd HH mmss"));
System timezone is New Zealand and the system date is 9 April 2012 which is New Zealand Standard Time.
C:\Dev\UtcModifiedDatetime\bin\Debug>UtcModifiedDatetime.exe M:\Test1\Test.txt
2012-04-09 3:53:46 pm Standard
20120409 03 5316
Now set the system date to 1 March 2012 which is New Zealand Daylight Time. Note that I have renamed the directory that contains the test file. This is important because otherwise Windows will cache the modified datetime of the file. I wasted a lot of time before I figured that out.
C:\Dev\UtcModifiedDatetime\bin\Debug>UtcModifiedDatetime.exe M:\Test2\Test.txt
2012-03-01 3:54:13 pm Daylight
20120409 02 5316
Now set the system date back to 9 April 2012 and change the timezone to Adelaide (UTC+09:30).
C:\Dev\UtcModifiedDatetime\bin\Debug>UtcModifiedDatetime.exe M:\Test3\Test.txt
2012-04-09 1:27:21 pm Standard
20120409 06 2316
So how can I get the correct modified datetime? I could try and figure out if the file is on a FAT32 file system and if it is daylight saving time make a one hour adjustment, but even if I could get that to work it would be a horrible ugly hack. Will using a low level system call work (I suspect not because the problem seems to be at the OS level)? Can I change the timezone of the process, without changing it on the whole machine? Is there any other way?
The problem is, FAT32 filesystem stores file time as a local time. Thus UTC time is a calculated time which takes DST into account, which results in a different UTC time. In general this problem is so complex, it's unsolvable.
For example you will need to store real UTC file modification time in a separate file, which must be synchronized on each machine before external drive is removed. If sync will not be preformed at least once, then it can't be considered correct. And there is no simple way to enforce that to users.