diff --git a/docs/en-us/guides/configuration/global.md b/docs/en-us/guides/configuration/global.md
index eb09371a..2de7bbf7 100644
--- a/docs/en-us/guides/configuration/global.md
+++ b/docs/en-us/guides/configuration/global.md
@@ -14,15 +14,12 @@ import { GANTT_GLOBAL_CONFIG } from 'ngx-gantt';
{
provide: GANTT_GLOBAL_CONFIG,
useValue: {
+ locale: 'zh-hans',
dateFormat: {
- ...
- },
- linkOptions: {
- ...
- },
- styleOptions: {
- ...
- },
+ timeZone: 'Asia/Shanghai',
+ weekStartsOn: 1
+ }
+ ...
}
},
...
@@ -41,6 +38,7 @@ export class AppModule {
export interface GanttGlobalConfig {
locale: GanttI18nLocale; // i18n locale zh-hans, zh-hant ,en-us, de-de, ja-jp, ru-ru
dateOptions: {
+ timeZone: string, // set custom time zone, default is system's time zone
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 // set the week start value, the default is 1
};
linkOptions: {
diff --git a/docs/en-us/guides/configuration/i18n.md b/docs/en-us/guides/configuration/i18n.md
index 55585656..349f2c1c 100644
--- a/docs/en-us/guides/configuration/i18n.md
+++ b/docs/en-us/guides/configuration/i18n.md
@@ -81,3 +81,31 @@ export class AppModule {
}
```
+
+### Configuring TimeZone
+
+`ngx-gantt` defaults to using the system timezone, but users can set a custom timezone through the global configuration `GANTT_GLOBAL_CONFIG` by specifying dateOptions.timeZone.
+
+```javascript
+import { GANTT_GLOBAL_CONFIG } from 'ngx-gantt';
+
+@NgModule({
+ ...
+ providers: [
+ {
+ provide: GANTT_GLOBAL_CONFIG,
+ useValue: {
+ dateOptions: {
+ timeZone: 'Asia/Shanghai'
+ }
+ }
+ },
+ ...
+ ]
+ ...
+})
+export class AppModule {
+
+}
+
+```
diff --git a/docs/zh-cn/guides/configuration/global.md b/docs/zh-cn/guides/configuration/global.md
index 34cff747..63615b0e 100644
--- a/docs/zh-cn/guides/configuration/global.md
+++ b/docs/zh-cn/guides/configuration/global.md
@@ -15,15 +15,12 @@ import { GANTT_GLOBAL_CONFIG } from 'ngx-gantt';
{
provide: GANTT_GLOBAL_CONFIG,
useValue: {
+ locale: 'zh-hans',
dateFormat: {
- ...
- },
- linkOptions: {
- ...
- },
- styleOptions: {
- ...
- },
+ timeZone: 'Asia/Shanghai',
+ weekStartsOn: 1
+ }
+ ...
}
},
...
@@ -36,12 +33,13 @@ export class AppModule {
```
-`GANTT_GLOBAL_CONFIG` 格式如下:
+`GANTT_GLOBAL_CONFIG` 参数说明:
```javascript
export interface GanttGlobalConfig {
locale: GanttI18nLocale; // 默认 locale 可选语言:zh-hans, zh-hant ,en-us, de-de, ja-jp, ru-ru
dateOptions: {
+ timeZone: string, // 设置自定义时区,默认为系统默认时区
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 // 设置 week 起始值,默认为 1
};
linkOptions: {
diff --git a/docs/zh-cn/guides/configuration/i18n.md b/docs/zh-cn/guides/configuration/i18n.md
index 31dfc13b..e30e3380 100644
--- a/docs/zh-cn/guides/configuration/i18n.md
+++ b/docs/zh-cn/guides/configuration/i18n.md
@@ -81,4 +81,33 @@ export class AppModule {
}
+```
+
+### 时区
+
+`ngx-gantt` 默认使用系统时区,使用者可通过全局配置 `GANTT_GLOBAL_CONFIG` 中的 `dateOptions.timeZone` 来设置自定义时区
+
+```javascript
+import { GANTT_GLOBAL_CONFIG } from 'ngx-gantt';
+
+@NgModule({
+ ...
+ providers: [
+ {
+ provide: GANTT_GLOBAL_CONFIG,
+ useValue: {
+ dateOptions: {
+ timeZone: 'Asia/Shanghai'
+ }
+ }
+ },
+ ...
+ ]
+ ...
+})
+export class AppModule {
+
+}
+
+
```
diff --git a/example/src/app/app.module.ts b/example/src/app/app.module.ts
index b252a24b..e298a937 100644
--- a/example/src/app/app.module.ts
+++ b/example/src/app/app.module.ts
@@ -8,7 +8,7 @@ import { ThyNotifyModule } from 'ngx-tethys/notify';
import { ThyDatePickerModule } from 'ngx-tethys/date-picker';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
-import { GANTT_GLOBAL_CONFIG, GANTT_I18N_LOCALE_TOKEN, GanttViewType, NgxGanttModule } from 'ngx-gantt';
+import { GANTT_GLOBAL_CONFIG, NgxGanttModule } from 'ngx-gantt';
import { AppComponent } from './app.component';
import { AppGanttExampleComponent } from './gantt/gantt.component';
import { AppRoutingModule } from './app-routing.module';
@@ -25,7 +25,6 @@ import { AppExampleComponentsComponent } from './components/components.component
import { AppGanttGroupsExampleComponent } from './gantt-groups/gantt-groups.component';
import { AppGanttCustomViewExampleComponent } from './gantt-custom-view/gantt.component';
import { AppGanttVirtualScrollExampleComponent } from './gantt-virtual-scroll/gantt.component';
-import { ko } from 'date-fns/locale';
@NgModule({
declarations: [
@@ -56,7 +55,17 @@ import { ko } from 'date-fns/locale';
ThyDatePickerModule,
...EXAMPLE_MODULES
],
- providers: [...DOCGENI_SITE_PROVIDERS],
+ providers: [
+ ...DOCGENI_SITE_PROVIDERS,
+ {
+ provide: GANTT_GLOBAL_CONFIG,
+ useValue: {
+ dateOptions: {
+ timeZone: 'America/New_York'
+ }
+ }
+ }
+ ],
bootstrap: [AppComponent]
})
export class AppModule {
diff --git a/example/src/app/gantt/gantt.component.html b/example/src/app/gantt/gantt.component.html
index 0735720f..04afc0ce 100644
--- a/example/src/app/gantt/gantt.component.html
+++ b/example/src/app/gantt/gantt.component.html
@@ -60,12 +60,12 @@
- {{ item.start * 1000 | date : 'yyyy-MM-dd HH:mm' }}
+ {{ item.start * 1000 | dateFormat : 'yyyy-MM-dd HH:mm' }}
- {{ item.end * 1000 | date : 'yyyy-MM-dd HH:mm' }}
+ {{ item.end * 1000 | dateFormat : 'yyyy-MM-dd HH:mm' }}
diff --git a/package-lock.json b/package-lock.json
index b6a15ac1..09e95e17 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,7 +19,8 @@
"@angular/platform-browser": "^18.2.0",
"@angular/platform-browser-dynamic": "^18.2.0",
"@angular/router": "^18.2.0",
- "date-fns": "^2.14.0",
+ "@date-fns/tz": "^1.2.0",
+ "date-fns": "^4.1.0",
"html2canvas": "1.0.0-rc.7",
"rxjs": "^7.5.5",
"tslib": "^2.3.0",
@@ -4649,6 +4650,12 @@
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
+ "node_modules/@date-fns/tz": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.2.0.tgz",
+ "integrity": "sha512-LBrd7MiJZ9McsOgxqWX7AaxrDjcFVjWH/tIKJd7pnR7McaslGYOP1QmmiBXdJH/H/yLCT+rcQ7FaPBUxRGUtrg==",
+ "license": "MIT"
+ },
"node_modules/@discoveryjs/json-ext": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.1.tgz",
@@ -11144,6 +11151,23 @@
"wrap-ansi": "^5.1.0"
}
},
+ "node_modules/concurrently/node_modules/date-fns": {
+ "version": "2.30.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
+ "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0"
+ },
+ "engines": {
+ "node": ">=0.11"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/date-fns"
+ }
+ },
"node_modules/concurrently/node_modules/decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
@@ -13279,15 +13303,22 @@
}
},
"node_modules/date-fns": {
- "version": "2.29.3",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
- "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==",
- "engines": {
- "node": ">=0.11"
- },
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
+ "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
+ "license": "MIT",
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/date-fns"
+ "type": "github",
+ "url": "https://github.com/sponsors/kossnocorp"
+ }
+ },
+ "node_modules/date-fns-tz": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.2.0.tgz",
+ "integrity": "sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "date-fns": "^3.0.0 || ^4.0.0"
}
},
"node_modules/date-format": {
@@ -29451,6 +29482,11 @@
}
}
},
+ "@date-fns/tz": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.2.0.tgz",
+ "integrity": "sha512-LBrd7MiJZ9McsOgxqWX7AaxrDjcFVjWH/tIKJd7pnR7McaslGYOP1QmmiBXdJH/H/yLCT+rcQ7FaPBUxRGUtrg=="
+ },
"@discoveryjs/json-ext": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.1.tgz",
@@ -34201,6 +34237,15 @@
"wrap-ansi": "^5.1.0"
}
},
+ "date-fns": {
+ "version": "2.30.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
+ "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.21.0"
+ }
+ },
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
@@ -35888,9 +35933,15 @@
}
},
"date-fns": {
- "version": "2.29.3",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
- "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
+ "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="
+ },
+ "date-fns-tz": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.2.0.tgz",
+ "integrity": "sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==",
+ "requires": {}
},
"date-format": {
"version": "4.0.14",
diff --git a/package.json b/package.json
index 0456d7a1..685896d5 100644
--- a/package.json
+++ b/package.json
@@ -46,7 +46,9 @@
"@angular/platform-browser": "^18.2.0",
"@angular/platform-browser-dynamic": "^18.2.0",
"@angular/router": "^18.2.0",
- "date-fns": "^2.14.0",
+ "@date-fns/tz": "^1.2.0",
+ "date-fns": "^4.1.0",
+ "date-fns-tz": "^3.2.0",
"html2canvas": "1.0.0-rc.7",
"rxjs": "^7.5.5",
"tslib": "^2.3.0",
diff --git a/packages/gantt/src/gantt-upper.ts b/packages/gantt/src/gantt-upper.ts
index bc82141d..2338b1fb 100644
--- a/packages/gantt/src/gantt-upper.ts
+++ b/packages/gantt/src/gantt-upper.ts
@@ -196,7 +196,7 @@ export abstract class GanttUpper implements OnChanges, OnInit, OnDestroy {
this.styles = Object.assign({}, this.configService.config.styleOptions, this.styles);
this.viewOptions.dateFormat = Object.assign({}, this.configService.config.dateFormat, this.viewOptions.dateFormat);
this.viewOptions.styleOptions = Object.assign({}, this.configService.config.styleOptions, this.viewOptions.styleOptions);
- this.viewOptions.dateDisplayFormats = this.configService.getViewsLocale()[this.viewType].dateFormats;
+ this.viewOptions.dateDisplayFormats = this.configService.getViewsLocale()[this.viewType]?.dateFormats;
this.view = createViewFactory(this.viewType, viewDate.start, viewDate.end, this.viewOptions);
}
diff --git a/packages/gantt/src/gantt.config.ts b/packages/gantt/src/gantt.config.ts
index 61f47358..6482acfc 100644
--- a/packages/gantt/src/gantt.config.ts
+++ b/packages/gantt/src/gantt.config.ts
@@ -23,6 +23,7 @@ export interface GanttDateOptions {
* http://gantt.ngnice.com/guides/configuration/i18n
*/
locale?: Locale;
+ timeZone?: string;
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
}
diff --git a/packages/gantt/src/gantt.module.ts b/packages/gantt/src/gantt.module.ts
index 3d46e953..8609d743 100644
--- a/packages/gantt/src/gantt.module.ts
+++ b/packages/gantt/src/gantt.module.ts
@@ -18,12 +18,13 @@ import { GanttTableHeaderComponent } from './components/table/header/gantt-table
import { NgxGanttToolbarComponent } from './components/toolbar/toolbar.component';
import { NgxGanttComponent } from './gantt.component';
import { GANTT_GLOBAL_CONFIG, GanttConfigService, GanttGlobalConfig, defaultConfig } from './gantt.config';
-import { IsGanttBarItemPipe, IsGanttCustomItemPipe, IsGanttRangeItemPipe } from './gantt.pipe';
+import { GanttDateFormatPipe, IsGanttBarItemPipe, IsGanttCustomItemPipe, IsGanttRangeItemPipe } from './gantt.pipe';
import { NgxGanttRootComponent } from './root.component';
import { NgxGanttTableColumnComponent } from './table/gantt-column.component';
import { NgxGanttTableComponent } from './table/gantt-table.component';
import { GanttScrollbarComponent } from './components/scrollbar/scrollbar.component';
import { i18nLocaleProvides } from './i18n';
+import { setDefaultTimeZone } from 'ngx-gantt';
@NgModule({
imports: [
@@ -50,7 +51,8 @@ import { i18nLocaleProvides } from './i18n';
GanttScrollbarComponent,
IsGanttRangeItemPipe,
IsGanttBarItemPipe,
- IsGanttCustomItemPipe
+ IsGanttCustomItemPipe,
+ GanttDateFormatPipe
],
exports: [
NgxGanttComponent,
@@ -64,7 +66,8 @@ import { i18nLocaleProvides } from './i18n';
GanttCalendarHeaderComponent,
GanttCalendarGridComponent,
GanttDragBackdropComponent,
- GanttScrollbarComponent
+ GanttScrollbarComponent,
+ GanttDateFormatPipe
],
providers: [
CdkVirtualScrollViewport,
@@ -78,9 +81,14 @@ import { i18nLocaleProvides } from './i18n';
export class NgxGanttModule {
constructor() {
const configService = inject(GanttConfigService);
+
setDefaultOptions({
locale: configService.getDateLocal(),
weekStartsOn: configService.config?.dateOptions?.weekStartsOn
});
+
+ if (configService.config.dateOptions?.timeZone) {
+ setDefaultTimeZone(configService.config.dateOptions.timeZone);
+ }
}
}
diff --git a/packages/gantt/src/gantt.pipe.ts b/packages/gantt/src/gantt.pipe.ts
index ba84a69a..7608d9e6 100644
--- a/packages/gantt/src/gantt.pipe.ts
+++ b/packages/gantt/src/gantt.pipe.ts
@@ -1,5 +1,6 @@
import { Pipe, PipeTransform } from '@angular/core';
import { GanttItemType } from './class';
+import { GanttDate } from './utils/date';
@Pipe({
name: 'isGanttRangeItem',
@@ -30,3 +31,13 @@ export class IsGanttCustomItemPipe implements PipeTransform {
return value === GanttItemType.custom;
}
}
+
+@Pipe({
+ name: 'dateFormat',
+ standalone: true
+})
+export class GanttDateFormatPipe implements PipeTransform {
+ transform(value: number | string, format: string) {
+ return new GanttDate(value).format(format);
+ }
+}
diff --git a/packages/gantt/src/utils/date.ts b/packages/gantt/src/utils/date.ts
index 0f5075da..d4e76ce8 100644
--- a/packages/gantt/src/utils/date.ts
+++ b/packages/gantt/src/utils/date.ts
@@ -29,9 +29,13 @@ import {
startOfMinute,
startOfHour,
endOfHour,
- endOfMinute
+ endOfMinute,
+ Locale,
+ FirstWeekContainsDate
} from 'date-fns';
+import { TZDate } from '@date-fns/tz';
+
export {
Locale,
addDays,
@@ -76,6 +80,12 @@ export {
export type GanttDateUtil = 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
+let timeZone: string;
+
+export function setDefaultTimeZone(zone: string) {
+ timeZone = zone ?? undefined;
+}
+
export class GanttDate {
value: Date;
@@ -85,9 +95,9 @@ export class GanttDate {
this.value = date;
} else if (typeof date === 'string' || typeof date === 'number') {
if (date.toString().length < 13) {
- this.value = fromUnixTime(+date);
+ this.value = new TZDate(fromUnixTime(+date), timeZone);
} else {
- this.value = new Date(date);
+ this.value = new TZDate(date as any, timeZone);
}
} else {
throw new Error(
@@ -96,7 +106,7 @@ export class GanttDate {
);
}
} else {
- this.value = new Date();
+ this.value = new TZDate(new Date(), timeZone);
}
}
@@ -280,7 +290,7 @@ export class GanttDate {
options?: {
locale?: Locale;
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
- firstWeekContainsDate?: number;
+ firstWeekContainsDate?: FirstWeekContainsDate;
useAdditionalWeekYearTokens?: boolean;
useAdditionalDayOfYearTokens?: boolean;
}