Skip to content

Commit 8b3d931

Browse files
committed
adds GetServerTimeZones method on ExchangeService class. fixes many issues related to timezone and DateTime, added build sequence text file for creating single file output.
1 parent 778ac63 commit 8b3d931

16 files changed

+1334
-132
lines changed

config/tsd.start

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
declare module "ews-javascript-api" {
2-
import moment = require('moment-timezone');
2+
import * as moment from 'moment-timezone';

gulpfile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ gulp.task("ts-def-prep", ["ts-def-compile"], function () {
202202
}))
203203
.pipe(concat("temp.d.ts"))
204204
.pipe(replace(/^.*import.*\{.*\}.*from.*\;/gm, ''))
205-
.pipe(replace("import moment = require('moment-timezone');", ''))
205+
.pipe(replace("import * as moment from 'moment-timezone';", ''))
206206
.pipe(replace(/^.*export.*\{.*\}.*from.*\;/gm, ''))
207207
.pipe(replace(/^.*export.*\{.*\};$/gm, ''))
208208
.pipe(replace(/^.*\/\/\/\s*\<reference.*\>/gm, ''))

singleFileBuildSequence.txt

Lines changed: 1024 additions & 0 deletions
Large diffs are not rendered by default.

src/js/ComplexProperties/Availability/Suggestion.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export class Suggestion extends ComplexProperty {
2525
LoadFromXmlJsObject(jsonProperty: any, service: ExchangeService): void {
2626

2727
this.date = DateTime.Parse(jsonProperty[XmlElementNames.Date]);
28+
console.log("bug: Suggestion->LoadFromXml: need to change to millisecond and with datetimekind")
29+
debugger;
2830
this.quality = <SuggestionQuality><any>SuggestionQuality[jsonProperty[XmlElementNames.DayQuality]];
2931

3032
var suggestionArrayObj: any = jsonProperty[XmlElementNames.SuggestionArray];

src/js/ComplexProperties/TimeZones/RelativeDayOfMonthTransition.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Convert } from "../../ExtensionMethods";
2-
import { DateTime } from "../../DateTime";
2+
import { DateTime, msToEpoch } from "../../DateTime";
33
import { DayOfTheWeek } from "../../Enumerations/DayOfTheWeek";
44
import { EwsLogging } from "../../Core/EwsLogging";
55
import { EwsServiceXmlWriter } from "../../Core/EwsServiceXmlWriter";
@@ -59,7 +59,7 @@ export class RelativeDayOfMonthTransition extends AbsoluteMonthTransition {
5959
*/
6060
CreateTransitionTime(): TimeZoneInfo.TransitionTime {
6161
return TimeZoneInfo.TransitionTime.CreateFloatingDateRule(
62-
new DateTime(this.TimeOffset.Milliseconds),
62+
new DateTime(this.TimeOffset.Milliseconds - msToEpoch),
6363
this.Month,
6464
this.WeekIndex == -1 ? 5 : this.WeekIndex,
6565
EwsUtilities.EwsToSystemDayOfWeek(this.DayOfTheWeek));

src/js/ComplexProperties/TimeZones/TimeZoneDefinition.ts

Lines changed: 71 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -286,77 +286,78 @@ export class TimeZoneDefinition extends ComplexProperty {
286286
* @param {ExchangeService} service The service.
287287
* @return {TimeZoneInfo} A TimeZoneInfo representing the same time zone as this definition.
288288
*/
289-
ToTimeZoneInfo(service?: ExchangeService): TimeZoneInfo {
289+
ToTimeZoneInfo(service?: ExchangeService, parse: boolean = false): TimeZoneInfo {
290290
this.Validate();
291291

292-
//ref: skipped creation based on server data, directly creating using TimeZone Mapping data. complex to translate Windows TimeZoneInfo subclasses to javascript.
293-
return TimeZoneInfo.FindSystemTimeZoneById(this.Id);
294-
295-
// let result: TimeZoneInfo;
296-
297-
// // Retrieve the base offset to UTC, standard and daylight display names from
298-
// // the last transition group, which is the one that currently applies given that
299-
// // transitions are ordered chronologically.
300-
// let creationParams: TimeZoneTransitionGroup.CustomTimeZoneCreateParams =
301-
// this.transitions[this.transitions.length - 1].TargetGroup.GetCustomTimeZoneCreationParams();
302-
303-
// let adjustmentRules: TimeZoneInfo.AdjustmentRule[] = [];
304-
305-
// let startDate: DateTime = DateTime.MinValue;
306-
// let endDate: DateTime;
307-
// let effectiveEndDate: DateTime;
308-
309-
// for (let i = 0; i < this.transitions.length; i++) {
310-
// if (i < this.transitions.length - 1) {
311-
// endDate = (this.transitions[i + 1] as AbsoluteDateTransition).DateTime;
312-
// effectiveEndDate = endDate.AddDays(-1);
313-
// }
314-
// else {
315-
// endDate = DateTime.MaxValue;
316-
// effectiveEndDate = endDate;
317-
// }
318-
319-
// // OM:1648848 Due to bad timezone data from clients the
320-
// // startDate may not always come before the effectiveEndDate
321-
// if (startDate < effectiveEndDate) {
322-
// let adjustmentRule: TimeZoneInfo.AdjustmentRule = this.transitions[i].TargetGroup.CreateAdjustmentRule(startDate, effectiveEndDate);
323-
324-
// if (adjustmentRule != null) {
325-
// adjustmentRules.push(adjustmentRule);
326-
// }
327-
328-
// startDate = endDate;
329-
// }
330-
// else {
331-
// // service.TraceMessage(
332-
// // TraceFlags.EwsTimeZones,
333-
// // string.Format(
334-
// // "The startDate '{0}' is not before the effectiveEndDate '{1}'. Will skip creating adjustment rule.",
335-
// // startDate,
336-
// // effectiveEndDate));
337-
// }
338-
// }
339-
340-
// if (adjustmentRules.length == 0) {
341-
// // If there are no adjustment rule, the time zone does not support Daylight
342-
// // saving time.
343-
// result = TimeZoneInfo.CreateCustomTimeZone(
344-
// this.Id,
345-
// creationParams.BaseOffsetToUtc,
346-
// this.Name,
347-
// creationParams.StandardDisplayName);
348-
// }
349-
// else {
350-
// result = TimeZoneInfo.CreateCustomTimeZone(
351-
// this.Id,
352-
// creationParams.BaseOffsetToUtc,
353-
// this.Name,
354-
// creationParams.StandardDisplayName,
355-
// creationParams.DaylightDisplayName,
356-
// adjustmentRules);
357-
// }
358-
359-
// return result;
292+
if (!parse) {
293+
//ref: skipped creation based on server data, directly creating using TimeZone Mapping data. complex to translate Windows TimeZoneInfo subclasses to javascript.
294+
return TimeZoneInfo.FindSystemTimeZoneById(this.Id);
295+
}
296+
let result: TimeZoneInfo;
297+
298+
// Retrieve the base offset to UTC, standard and daylight display names from
299+
// the last transition group, which is the one that currently applies given that
300+
// transitions are ordered chronologically.
301+
let creationParams: TimeZoneTransitionGroup.CustomTimeZoneCreateParams =
302+
this.transitions[this.transitions.length - 1].TargetGroup.GetCustomTimeZoneCreationParams();
303+
304+
let adjustmentRules: TimeZoneInfo.AdjustmentRule[] = [];
305+
306+
let startDate: DateTime = DateTime.MinValue;
307+
let endDate: DateTime;
308+
let effectiveEndDate: DateTime;
309+
310+
for (let i = 0; i < this.transitions.length; i++) {
311+
if (i < this.transitions.length - 1) {
312+
endDate = (this.transitions[i + 1] as AbsoluteDateTransition).DateTime;
313+
effectiveEndDate = endDate.AddDays(-1);
314+
}
315+
else {
316+
endDate = DateTime.MaxValue;
317+
effectiveEndDate = endDate;
318+
}
319+
320+
// OM:1648848 Due to bad timezone data from clients the
321+
// startDate may not always come before the effectiveEndDate
322+
if (startDate < effectiveEndDate) {
323+
let adjustmentRule: TimeZoneInfo.AdjustmentRule = this.transitions[i].TargetGroup.CreateAdjustmentRule(startDate, effectiveEndDate);
324+
325+
if (adjustmentRule != null) {
326+
adjustmentRules.push(adjustmentRule);
327+
}
328+
329+
startDate = endDate;
330+
}
331+
else {
332+
// service.TraceMessage(
333+
// TraceFlags.EwsTimeZones,
334+
// string.Format(
335+
// "The startDate '{0}' is not before the effectiveEndDate '{1}'. Will skip creating adjustment rule.",
336+
// startDate,
337+
// effectiveEndDate));
338+
}
339+
}
340+
341+
if (adjustmentRules.length == 0) {
342+
// If there are no adjustment rule, the time zone does not support Daylight
343+
// saving time.
344+
result = TimeZoneInfo.CreateCustomTimeZone(
345+
this.Id,
346+
creationParams.BaseOffsetToUtc,
347+
this.Name,
348+
creationParams.StandardDisplayName);
349+
}
350+
else {
351+
result = TimeZoneInfo.CreateCustomTimeZone(
352+
this.Id,
353+
creationParams.BaseOffsetToUtc,
354+
this.Name,
355+
creationParams.StandardDisplayName,
356+
creationParams.DaylightDisplayName,
357+
adjustmentRules);
358+
}
359+
360+
return result;
360361
}
361362

362363
/**
@@ -380,7 +381,7 @@ export class TimeZoneDefinition extends ComplexProperty {
380381
for (let transition of this.transitions) {
381382
//Type transitionType = transition.GetType();
382383

383-
if (!(transition instanceof TimeZoneTransition) && !(transition instanceof AbsoluteDateTransition)) {
384+
if (!(transition instanceof TimeZoneTransition) && !(<any>transition instanceof AbsoluteDateTransition)) {
384385
throw new ServiceLocalException(Strings.InvalidOrUnsupportedTimeZoneDefinition);
385386
}
386387

src/js/ComplexProperties/TimeZones/TimeZoneTransition.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,9 @@ export class TimeZoneTransition extends ComplexProperty {
226226
super.WriteToXml(writer, this.GetXmlElementName());
227227
}
228228
}
229+
230+
export module TimeZoneTransition {
231+
export var AbsoluteDateTransition;
232+
export var AbsoluteDayOfMonthTransition;
233+
export var RelativeDayOfMonthTransition;
234+
}

src/js/ComplexProperties/TimeZones/TimeZoneTransitionGroup.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,16 @@ export class TimeZoneTransitionGroup extends ComplexProperty {
4141
* Gets the transition to the Daylight period.
4242
*/
4343
private get TransitionToDaylight(): TimeZoneTransition {
44-
this.InitializeTransitions(); return this.TransitionToDaylight;
44+
this.InitializeTransitions();
45+
return this.transitionToDaylight;
4546
}
4647

4748
/**
4849
* Gets the transition to the Standard period.
4950
*/
5051
private get TransitionToStandard(): TimeZoneTransition {
51-
this.InitializeTransitions(); return this.transitionToStandard;
52+
this.InitializeTransitions();
53+
return this.transitionToStandard;
5254
}
5355

5456
/**
@@ -251,9 +253,16 @@ export class TimeZoneTransitionGroup extends ComplexProperty {
251253
// If there are two transitions, none of them should be of type TimeZoneTransition
252254
if (this.transitions.length == 2) {
253255
for (let transition of this.transitions) {
254-
if (transition instanceof TimeZoneTransition) {
255-
throw new ServiceLocalException(Strings.InvalidOrUnsupportedTimeZoneDefinition);
256+
try {
257+
let type = (<any>transition.constructor).name;
258+
//if (transition instanceof TimeZoneTransition) { // ref: can not use due to prototype chain issue
259+
if (type === "TimeZoneTransition") {
260+
throw new ServiceLocalException(Strings.InvalidOrUnsupportedTimeZoneDefinition);
261+
}
262+
} catch (error) {
263+
256264
}
265+
257266
}
258267
}
259268

src/js/Core/ExchangeService.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ import { GetRoomListsRequest } from "./Requests/GetRoomListsRequest";
116116
import { GetRoomsRequest } from "./Requests/GetRoomsRequest";
117117
import { GetSearchableMailboxesRequest } from "./Requests/GetSearchableMailboxesRequest";
118118
import { GetSearchableMailboxesResponse } from "./Responses/GetSearchableMailboxesResponse";
119+
import { GetServerTimeZonesRequest } from "./Requests/GetServerTimeZonesRequest";
120+
import { GetServerTimeZonesResponse } from "./Responses/GetServerTimeZonesResponse";
119121
import { GetUserAvailabilityRequest } from "./Requests/GetUserAvailabilityRequest";
120122
import { GetUserAvailabilityResults } from "../Misc/Availability/GetUserAvailabilityResults";
121123
import { GetUserConfigurationRequest } from "./Requests/GetUserConfigurationRequest";
@@ -128,14 +130,14 @@ import { GroupedFindItemsResults } from "../Search/GroupedFindItemsResults";
128130
import { Grouping } from "../Search/Grouping";
129131
import { Guid } from "../Guid";
130132
import { HoldAction } from "../Enumerations/HoldAction";
131-
import { IdFormat } from "../Enumerations/IdFormat";
132133
import { IFileAttachmentContentHandler } from "../Interfaces/IFileAttachmentContentHandler";
134+
import { IXHROptions } from "../Interfaces";
135+
import { IdFormat } from "../Enumerations/IdFormat";
133136
import { ImpersonatedUserId } from "../Misc/ImpersonatedUserId";
134137
import { InstallAppRequest } from "./Requests/InstallAppRequest";
135138
import { Item } from "./ServiceObjects/Items/Item";
136139
import { ItemChange } from "../Sync/ItemChange";
137140
import { ItemId } from "../ComplexProperties/ItemId";
138-
import { IXHROptions } from "../Interfaces";
139141
import { KeyValuePair } from "../AltDictionary";
140142
import { Mailbox } from "../ComplexProperties/Mailbox";
141143
import { MailboxQuery } from "../MailboxSearch/MailboxQuery";
@@ -4297,7 +4299,23 @@ export class ExchangeService extends ExchangeServiceBase {
42974299
}
42984300
/* #endregion Utilities */
42994301

4302+
//#region Additional Operations not in official EWS Managed Api in the commit
43004303

4304+
/**
4305+
* Get the TimeZoneInfo objects from server
4306+
*
4307+
* @returns {Promise<TimeZoneInfo[]>}
4308+
*/
4309+
GetServerTimeZones(): Promise<TimeZoneInfo[]> {
4310+
let argsLength = arguments.length;
4311+
let request: GetServerTimeZonesRequest = new GetServerTimeZonesRequest(this);
4312+
4313+
return request.Execute().then((response: ServiceResponseCollection<GetServerTimeZonesResponse>) => {
4314+
return response.Responses[0].TimeZones;
4315+
});
4316+
}
4317+
4318+
//#endregion
43014319
}
43024320

43034321
//module ExchangeService { -> moved to its own file to remove circular dependency.

0 commit comments

Comments
 (0)