Skip to content

Commit 8af0db3

Browse files
authored
Merge pull request #159 from gregolsky/v4.0
Enhance dates storage
2 parents d4c09fa + f588ee6 commit 8af0db3

File tree

15 files changed

+629
-285
lines changed

15 files changed

+629
-285
lines changed

package-lock.json

Lines changed: 255 additions & 255 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
"bluebird": "^3.4.7",
7575
"change-case": "^3.0.2",
7676
"md5-hex": "^2.0.0",
77-
"moment": "^2.22.0",
77+
"moment": "^2.22.2",
7878
"pluralize": "^4.0.0",
7979
"qs": "^6.5.2",
8080
"readable-stream": "^3.0.6",

src/Documents/Commands/GetRevisionsCommand.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export class GetRevisionsCommand extends RavenCommand<IRavenArrayResult> {
7070
}
7171

7272
if (this._before) {
73-
uri += "&before=" + DateUtil.stringify(this._before);
73+
uri += "&before=" + DateUtil.default.stringify(this._before);
7474
}
7575

7676
if (!TypeUtil.isNullOrUndefined(this._start)) {

src/Documents/Conventions/DocumentConventions.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { ReadBalanceBehavior } from "../../Http/ReadBalanceBehavior";
1313
import { throwError } from "../../Exceptions";
1414
import { CONSTANTS } from "../../Constants";
1515
import { TypeUtil } from "../../Utility/TypeUtil";
16-
import { DateUtil } from "../../Utility/DateUtil";
16+
import { DateUtil, DateUtilOpts } from "../../Utility/DateUtil";
1717
import { CasingConvention, ObjectUtil, ObjectChangeCaseOptions } from "../../Utility/ObjectUtil";
1818
import { JsonSerializer } from "../../Mapping/Json/Serializer";
1919

@@ -71,6 +71,7 @@ export class DocumentConventions {
7171
private _remoteEntityFieldNameConvention: CasingConvention;
7272

7373
private _objectMapper: TypesAwareObjectMapper;
74+
private _dateUtil: DateUtil;
7475

7576
private _useCompression;
7677

@@ -116,16 +117,24 @@ export class DocumentConventions {
116117
});
117118

118119
this._useCompression = null;
120+
121+
this._dateUtilOpts = {};
122+
this._dateUtil = new DateUtil(this._dateUtilOpts);
119123
}
120124

121125
public get objectMapper(): TypesAwareObjectMapper {
122126
return this._objectMapper;
123127
}
124128

125129
public set objectMapper(value: TypesAwareObjectMapper) {
130+
this._assertNotFrozen();
126131
this._objectMapper = value;
127132
}
128133

134+
public get dateUtil(): DateUtil {
135+
return this._dateUtil;
136+
}
137+
129138
public get readBalanceBehavior(): ReadBalanceBehavior {
130139
return this._readBalanceBehavior;
131140
}
@@ -196,6 +205,26 @@ export class DocumentConventions {
196205
this._useCompression = value;
197206
}
198207

208+
private _dateUtilOpts: DateUtilOpts;
209+
210+
public get storeDatesInUtc() {
211+
return this._dateUtilOpts.useUtcDates;
212+
}
213+
214+
public set storeDatesInUtc(value) {
215+
this._assertNotFrozen();
216+
this._dateUtilOpts.useUtcDates = value;
217+
}
218+
219+
public get storeDatesWithTimezoneInfo() {
220+
return this._dateUtilOpts.withTimezone;
221+
}
222+
223+
public set storeDatesWithTimezoneInfo(value) {
224+
this._assertNotFrozen();
225+
this._dateUtilOpts.withTimezone = true;
226+
}
227+
199228
/**
200229
* If set to 'true' then it will throw an exception when any query is performed (in session)
201230
* without explicit page size set.

src/Documents/Identity/Commands/NextHiloCommand.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export class NextHiloCommand extends RavenCommand<HiLoResult> {
5252

5353
public createRequest(node: ServerNode): HttpRequestParameters {
5454
const lastRangeAt: string = this._lastRangeAt
55-
? DateUtil.stringify(this._lastRangeAt)
55+
? DateUtil.default.stringify(this._lastRangeAt)
5656
: "";
5757

5858
const queryString = qs.stringify({

src/Documents/Session/AbstractDocumentQuery.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ export abstract class AbstractDocumentQuery<T extends object, TSelf extends Abst
389389

390390
private _stringifyParameter(value: any) {
391391
if (TypeUtil.isDate(value)) {
392-
return DateUtil.stringify(value);
392+
return DateUtil.default.stringify(value);
393393
}
394394

395395
if (TypeUtil.isString(value)) {

src/Documents/Session/InMemoryDocumentSessionOperations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ export abstract class InMemoryDocumentSessionOperations
294294

295295
const documentInfo = this._getDocumentInfo(instance);
296296
const lastModified = documentInfo.metadata[CONSTANTS.Documents.Metadata.LAST_MODIFIED];
297-
return DateUtil.parse(lastModified);
297+
return DateUtil.default.parse(lastModified);
298298
}
299299

300300
/**

src/Mapping/ObjectMapper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ export class TypesAwareObjectMapper implements ITypesAwareObjectMapper {
298298
}
299299

300300
if (fieldTypeName === "date") {
301-
fieldContext.setValue(DateUtil.parse(fieldVal));
301+
fieldContext.setValue(this._conventions.dateUtil.parse(fieldVal));
302302
return;
303303
}
304304

@@ -386,7 +386,7 @@ export class TypesAwareObjectMapper implements ITypesAwareObjectMapper {
386386
[objPathPrefix]: "date"
387387
});
388388

389-
return DateUtil.stringify(obj as Date);
389+
return this._conventions.dateUtil.stringify(obj as Date);
390390
}
391391

392392
if (TypeUtil.isSet(obj)) {

src/Utility/DateUtil.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
import * as moment from "moment";
2+
import { throwError } from "../Exceptions";
3+
4+
export interface DateUtilOpts {
5+
withTimezone?: boolean;
6+
useUtcDates?: boolean;
7+
}
28

39
export class DateUtil {
410

511
public static DEFAULT_DATE_FORMAT = "YYYY-MM-DDTHH:mm:ss.SSS0000";
12+
public static DEFAULT_DATE_TZ_FORMAT = "YYYY-MM-DDTHH:mm:ss.SSS0000Z";
13+
14+
public static default: DateUtil = new DateUtil({});
15+
16+
public constructor(private _opts: DateUtilOpts) {}
617

718
public static timestamp(): number {
819
return moment().unix();
@@ -16,26 +27,39 @@ export class DateUtil {
1627
return moment([1, 1, 1]).toDate();
1728
}
1829

19-
public static parse(dateString: string): Date {
30+
public parse(dateString: string): Date {
2031
if (!dateString) {
2132
return null;
2233
}
2334

24-
const stripped = dateString.substring(0, dateString.length - 1);
25-
const format = this.DEFAULT_DATE_FORMAT;
26-
27-
if (!dateString.endsWith("Z")) {
28-
const parsed = moment(dateString, format);
35+
let parsed;
36+
if (this._opts.useUtcDates || this._opts.withTimezone) {
37+
parsed = moment.parseZone(dateString, DateUtil.DEFAULT_DATE_TZ_FORMAT);
38+
} else {
39+
parsed = moment(dateString, DateUtil.DEFAULT_DATE_FORMAT);
40+
}
2941

30-
if (parsed.isValid()) {
31-
return parsed.toDate();
32-
}
42+
if (!parsed.isValid()) {
43+
throwError("InvalidArgumentException", `Could not parse date string '${dateString}'.`);
3344
}
3445

35-
return moment(stripped, format).toDate();
46+
return parsed.toDate();
3647
}
3748

38-
public static stringify(date: Date): string {
39-
return moment(date).format(this.DEFAULT_DATE_FORMAT);
49+
public stringify(date: Date): string {
50+
const m = moment(date);
51+
if (this._opts.useUtcDates) {
52+
m.utc();
53+
}
54+
55+
const format = this._opts.withTimezone
56+
? DateUtil.DEFAULT_DATE_TZ_FORMAT
57+
: DateUtil.DEFAULT_DATE_FORMAT;
58+
const result = m.format(format);
59+
if (this._opts.useUtcDates && !this._opts.withTimezone) {
60+
return result + "Z";
61+
}
62+
63+
return result;
4064
}
4165
}

test/Issues/RDBC_233.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ import { PatchRequest } from "../../src/Documents/Operations/PatchRequest";
1717
describe("RDBC-233", function () {
1818

1919
let mapper: TypesAwareObjectMapper;
20+
let conventions;
2021

2122
beforeEach(() => {
23+
conventions = DocumentConventions.defaultConventions;
2224
mapper = new TypesAwareObjectMapper({
23-
documentConventions: DocumentConventions.defaultConventions
25+
documentConventions: conventions
2426
});
2527
});
2628

@@ -45,8 +47,12 @@ describe("RDBC-233", function () {
4547
assert.ok(result);
4648
assert.strictEqual(result.date, null);
4749
assert.ok(result.anotherOne.start instanceof Date);
48-
assert.strictEqual(result.anotherOne.start.toString(), DateUtil.parse(obj.anotherOne.start).toString());
49-
assert.strictEqual(result.anotherOne.end.toString(), DateUtil.parse(obj.anotherOne.end).toString());
50+
assert.strictEqual(
51+
result.anotherOne.start.toString(),
52+
DocumentConventions.defaultConventions.dateUtil.parse(obj.anotherOne.start).toString());
53+
assert.strictEqual(
54+
result.anotherOne.end.toString(),
55+
DocumentConventions.defaultConventions.dateUtil.parse(obj.anotherOne.end).toString());
5056
});
5157

5258
describe("entire flow - store, patch, load", async () => {

0 commit comments

Comments
 (0)