Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TimeZone trouble #9

Closed
svrooij opened this issue Jul 25, 2017 · 10 comments
Closed

TimeZone trouble #9

svrooij opened this issue Jul 25, 2017 · 10 comments
Assignees

Comments

@svrooij
Copy link

svrooij commented Jul 25, 2017

Could you guys make the Id of TimeZoneDefinition overridable? And TimeZoneDefinition public?

Why I'm asking: Normally you could set the TimeZone of appointments with this property. By setting the correct timezone while creating the ExchangeService, but on Unix the TimeZoneIds are different then the ones Exchange is expecting.

Unix: Europe/Amsterdam
Windows (and Exchange): W. Europe Standard Time

If you would know what you're doing this smallllll change would solve a lot of TimeZone trouble for this project, which is really great by the way!!!

@sherlock1982
Copy link
Owner

Well I don't quite understand what are you trying to achieve. .NETStandard has a limited support of TimeZones. And you can see it in TimeZoneExtensions.cs.

Mostly because there's no TimeZoneInfo.GetAdjustmentRules function TimeZoneDefinition class becomes a bit of a fake which only makes sense for UTC.

Could you supply UTC Timezone when creating ExchangeService object and handle all timezone conversions for yourself? Than all your internal timezone issues will go away I suppose.

@svrooij
Copy link
Author

svrooij commented Jul 26, 2017

I know about the limited support for timezones in .NET Standard. That is why I would like to only override the id that gets serialized in the request. Which is in timezonedefinition.

The conversions rules are correctly loaded from the timezone, but if the timezone sn't correct Outlook shows that the appointment is in an other timezone ("West Africa" with the same offset). And because the users timezone is not the same as the appointment timezone it shows up at the correct time (e.g. 08:30) but it shows 07:30 GMT +1 in the appointment.

This is very confusing for the user and I think it is an Exchange bug, but if only the ID would be overridden before it gets put in the soap header, all the confusion disappears. And the actual ID that gets serialized is in TimeZoneDefinition and not in the sealed class TimeZoneInfo.

Sorry if I didn't explain it correctly it is a complex issue. (with a possibly easy fix)

This could also be a solution in ExchangeServiceBase

public string CustomTimeZoneId {get; set;}
/// <summary>
/// Gets a time zone definition generated from the time zone info to which this service is scoped.
/// </summary>
internal TimeZoneDefinition TimeZoneDefinition
{
    get
    {
        if (this.timeZoneDefinition == null)
        {
            this.timeZoneDefinition = new TimeZoneDefinition(this.TimeZone);
            if(!string.IsNullOrEmpty(CustomTimeZoneId))
                this.TimeZoneDefinition.Id = CustomTimeZoneId;
        }

        return this.timeZoneDefinition;
    }
}

@sherlock1982
Copy link
Owner

Do you know that with NET Core 2.0 you can create custom timezone and supply it to ExchangeService ? So you can have any id you want:

    public static void Main(string[] args)
    {
        TimeZoneInfo.TransitionTime start = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 1, 0, 0), 3, 5, DayOfWeek.Sunday);
        TimeZoneInfo.TransitionTime end = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 10, 5, DayOfWeek.Sunday);
        TimeZoneInfo.AdjustmentRule rule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(DateTime.MinValue.Date, DateTime.MaxValue.Date, new TimeSpan(1, 0, 0), start, end);

        var timezone = TimeZoneInfo.CreateCustomTimeZone("Europe/London", new TimeSpan(0), "Europe/London", "British Standard Time", "British Summer Time", new TimeZoneInfo.AdjustmentRule[] { rule });
    }

Does that help?
Well I'm just trying to avoid unnecessary changes in the lib. Soon 2.0 will be released and we will have much more API's available than now.

@svrooij
Copy link
Author

svrooij commented Jul 26, 2017

That would help a little, sadly the roadmap says it will not be released before Q3.

And that would also make the developer responsible for setting the daylight saving stuff and all the other properties. While the timezone info is correct only Exchange just wants the Windows ID. So sending the Unix ID results in user notices that the appointment is in some other timezone.

After thinking about this some more it would even make sense in making a translation table and always translate the timezone id to the Windows version before putting it in the soap header. Because setting the timezone to "Europe/Amsterdam" (GMT+1) results in "West Africa" (also GMT+1). That makes me wonder how it works, on the Exchange side. Think it tries to match the the id and if it isn't in the list of time zones it just takes the first one with the same offset.

@mattjohnsonpint
Copy link

It seems that this library could take a dependency on my TimeZoneConverter library to resolve this problem.

@svrooij
Copy link
Author

svrooij commented Jul 27, 2017

So concluding the strange issues with Exchange choosing the wrong timezone for appointments created with this library, could be solved by replacing this part with:

using System.Runtime.InteropServices;
using TimeZoneConvert;
...

/// <summary>
/// Gets a time zone definition generated from the time zone info to which this service is scoped.
/// </summary>
internal TimeZoneDefinition TimeZoneDefinition
{
    get
    {
        if (this.timeZoneDefinition == null)
        {
            this.timeZoneDefinition = new TimeZoneDefinition(this.TimeZone);
            if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                this.TimeZoneDefinition.Id = TZConvert.IanaToWindows(this.TimeZone.Id);
        }

        return this.timeZoneDefinition;
    }
}

What do you think about that @sherlock1982??? In my opinion it is wrong to send a TimeZoneId to Exchange that it doesn't understand. And instead of creating something to convert the IDs this library could be using an already existing lib for that.

@sherlock1982 sherlock1982 self-assigned this Jul 27, 2017
@mattjohnsonpint
Copy link

Note that if one wanted to not take a hard dependency, you could simply expose some settings property that is a Func<string, string> such that the user can wire it up themselves.

@sherlock1982
Copy link
Owner

sherlock1982 commented Jul 29, 2017

Made this code available:

    var service = new ExchangeService();
    if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
           service.TimeZoneDefinition.Id = TZConvert.IanaToWindows(service.TimeZone.Id);

@svrooij
Copy link
Author

svrooij commented Jul 31, 2017

@sherlock1982 this fix works perfectly! Thanks for the help.

@walsaadysixco
Copy link

walsaadysixco commented Feb 10, 2020

Made this code available:

    var service = new ExchangeService();
    if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
           service.TimeZoneDefinition.Id = TZConvert.IanaToWindows(service.TimeZone.Id);

What if I need to change the default timezone? The following doesn't work:

var ewsService = new ExchangeService(ExchangeVersion.Exchange2016, TZConvert.GetTimeZoneInfo("Arabian Standard Time"));
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
     ewsService.TimeZoneDefinition.Id = TZConvert.IanaToWindows(ewsService.TimeZone.Id);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants