diff --git a/frontend/src/app/app.constants.ts b/frontend/src/app/app.constants.ts
index cef630984..7cc4b4dff 100644
--- a/frontend/src/app/app.constants.ts
+++ b/frontend/src/app/app.constants.ts
@@ -439,4 +439,39 @@ export const fiatCurrencies = {
code: 'ZAR',
indexed: true,
},
-};
\ No newline at end of file
+};
+
+export interface Timezone {
+ offset: string;
+ name: string;
+}
+
+export const timezones: Timezone[] = [
+ { offset: '-12', name: 'Anywhere on Earth (AoE)' },
+ { offset: '-11', name: 'Samoa Standard Time (SST)' },
+ { offset: '-10', name: 'Hawaii-Aleutian Standard Time (HST)' },
+ { offset: '-9', name: 'Alaska Standard Time (AKST)' },
+ { offset: '-8', name: 'Pacific Standard Time (PST)' },
+ { offset: '-7', name: 'Mountain Standard Time (MST)' },
+ { offset: '-6', name: 'Central Standard Time (CST)' },
+ { offset: '-5', name: 'Eastern Standard Time (EST)' },
+ { offset: '-4', name: 'Atlantic Standard Time (AST)' },
+ { offset: '-3', name: 'Argentina Time (ART)' },
+ { offset: '-2', name: 'Fernando de Noronha Time (FNT)' },
+ { offset: '-1', name: 'Azores Time (AZOT)' },
+ { offset: '+0', name: 'Greenwich Mean Time (GMT)' },
+ { offset: '+1', name: 'Central European Time (CET)' },
+ { offset: '+2', name: 'Eastern European Time (EET)' },
+ { offset: '+3', name: 'Moscow Standard Time (MSK)' },
+ { offset: '+4', name: 'Armenia Time (AMT)' },
+ { offset: '+5', name: 'Pakistan Standard Time (PKT)' },
+ { offset: '+6', name: 'Xinjiang Time (XJT)' },
+ { offset: '+7', name: 'Indochina Time (ICT)' },
+ { offset: '+8', name: 'Hong Kong Time (HKT)' },
+ { offset: '+9', name: 'Japan Standard Time (JST)' },
+ { offset: '+10', name: 'Australian Eastern Standard Time (AEST)' },
+ { offset: '+11', name: 'Norfolk Time (NFT)' },
+ { offset: '+12', name: 'New Zealand Standard Time (NZST)' },
+ { offset: '+13', name: 'Tonga Time (TOT)' },
+ { offset: '+14', name: 'Line Islands Time (LINT)' }
+];
\ No newline at end of file
diff --git a/frontend/src/app/components/timezone-selector/timezone-selector.component.html b/frontend/src/app/components/timezone-selector/timezone-selector.component.html
new file mode 100644
index 000000000..bd959ac3d
--- /dev/null
+++ b/frontend/src/app/components/timezone-selector/timezone-selector.component.html
@@ -0,0 +1,8 @@
+
+
+
diff --git a/frontend/src/app/components/timezone-selector/timezone-selector.component.scss b/frontend/src/app/components/timezone-selector/timezone-selector.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/frontend/src/app/components/timezone-selector/timezone-selector.component.ts b/frontend/src/app/components/timezone-selector/timezone-selector.component.ts
new file mode 100644
index 000000000..44c04354e
--- /dev/null
+++ b/frontend/src/app/components/timezone-selector/timezone-selector.component.ts
@@ -0,0 +1,58 @@
+import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
+import { StorageService } from '@app/services/storage.service';
+import { StateService } from '@app/services/state.service';
+import { timezones } from '@app/app.constants';
+
+
+@Component({
+ selector: 'app-timezone-selector',
+ templateUrl: './timezone-selector.component.html',
+ styleUrls: ['./timezone-selector.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class TimezoneSelectorComponent implements OnInit {
+ timezoneForm: UntypedFormGroup;
+ timezones = timezones;
+ localTimezoneOffset: string = '';
+ localTimezoneName: string;
+
+ constructor(
+ private formBuilder: UntypedFormBuilder,
+ private stateService: StateService,
+ private storageService: StorageService,
+ ) { }
+
+ ngOnInit() {
+ this.setLocalTimezone();
+ this.timezoneForm = this.formBuilder.group({
+ mode: ['local'],
+ });
+ this.stateService.timezone$.subscribe((mode) => {
+ this.timezoneForm.get('mode')?.setValue(mode);
+ });
+ }
+
+ changeMode() {
+ const newMode = this.timezoneForm.get('mode')?.value;
+ this.storageService.setValue('timezone-preference', newMode);
+ this.stateService.timezone$.next(newMode);
+ }
+
+ setLocalTimezone() {
+ const offset = new Date().getTimezoneOffset();
+ const sign = offset <= 0 ? "+" : "-";
+ const absOffset = Math.abs(offset);
+ const hours = String(Math.floor(absOffset / 60));
+ const minutes = String(absOffset % 60).padStart(2, '0');
+ if (minutes === '00') {
+ this.localTimezoneOffset = `${sign}${hours}`;
+ } else {
+ this.localTimezoneOffset = `${sign}${hours.padStart(2, '0')}:${minutes}`;
+ }
+
+ const timezone = this.timezones.find(tz => tz.offset === this.localTimezoneOffset);
+ this.timezones = this.timezones.filter(tz => tz.offset !== this.localTimezoneOffset && tz.offset !== '+0');
+ this.localTimezoneName = timezone ? timezone.name : '';
+ }
+}
diff --git a/frontend/src/app/services/state.service.ts b/frontend/src/app/services/state.service.ts
index 2feb266d1..0d006b552 100644
--- a/frontend/src/app/services/state.service.ts
+++ b/frontend/src/app/services/state.service.ts
@@ -186,6 +186,7 @@ export class StateService {
live2Chart$ = new Subject();
viewAmountMode$: BehaviorSubject<'btc' | 'sats' | 'fiat'>;
+ timezone$: BehaviorSubject;
connectionState$ = new BehaviorSubject<0 | 1 | 2>(2);
isTabHidden$: Observable;
@@ -347,6 +348,9 @@ export class StateService {
const viewAmountModePreference = this.storageService.getValue('view-amount-mode') as 'btc' | 'sats' | 'fiat';
this.viewAmountMode$ = new BehaviorSubject<'btc' | 'sats' | 'fiat'>(viewAmountModePreference || 'btc');
+ const timezonePreference = this.storageService.getValue('timezone-preference');
+ this.timezone$ = new BehaviorSubject(timezonePreference || 'local');
+
this.backend$.subscribe(backend => {
this.backend = backend;
});
diff --git a/frontend/src/app/shared/components/global-footer/global-footer.component.html b/frontend/src/app/shared/components/global-footer/global-footer.component.html
index d82bb8062..7f51c3ede 100644
--- a/frontend/src/app/shared/components/global-footer/global-footer.component.html
+++ b/frontend/src/app/shared/components/global-footer/global-footer.component.html
@@ -30,7 +30,7 @@
diff --git a/frontend/src/app/shared/components/timestamp/timestamp.component.html b/frontend/src/app/shared/components/timestamp/timestamp.component.html
index 7b77cb1a3..097867b42 100644
--- a/frontend/src/app/shared/components/timestamp/timestamp.component.html
+++ b/frontend/src/app/shared/components/timestamp/timestamp.component.html
@@ -1,6 +1,6 @@
-
- {{ seconds * 1000 | date: customFormat ?? 'yyyy-MM-dd HH:mm' }}
+ {{ seconds * 1000 | date: customFormat ?? 'yyyy-MM-dd HH:mm' : (stateService.timezone$ | async) }}
diff --git a/frontend/src/app/shared/components/timestamp/timestamp.component.ts b/frontend/src/app/shared/components/timestamp/timestamp.component.ts
index aace6efbf..5ca6a750b 100644
--- a/frontend/src/app/shared/components/timestamp/timestamp.component.ts
+++ b/frontend/src/app/shared/components/timestamp/timestamp.component.ts
@@ -1,4 +1,5 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
+import { StateService } from '@app/services/state.service';
@Component({
selector: 'app-timestamp',
@@ -16,6 +17,10 @@ export class TimestampComponent implements OnChanges {
seconds: number | undefined = undefined;
+ constructor(
+ public stateService: StateService,
+ ) { }
+
ngOnChanges(): void {
if (this.unixTime) {
this.seconds = this.unixTime;
diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts
index a855f11b5..ce5ac0f65 100644
--- a/frontend/src/app/shared/shared.module.ts
+++ b/frontend/src/app/shared/shared.module.ts
@@ -36,6 +36,7 @@ import { FiatSelectorComponent } from '@components/fiat-selector/fiat-selector.c
import { RateUnitSelectorComponent } from '@components/rate-unit-selector/rate-unit-selector.component';
import { ThemeSelectorComponent } from '@components/theme-selector/theme-selector.component';
import { AmountSelectorComponent } from '@components/amount-selector/amount-selector.component';
+import { TimezoneSelectorComponent } from '@components/timezone-selector/timezone-selector.component';
import { BrowserOnlyDirective } from '@app/shared/directives/browser-only.directive';
import { ServerOnlyDirective } from '@app/shared/directives/server-only.directive';
import { ColoredPriceDirective } from '@app/shared/directives/colored-price.directive';
@@ -134,6 +135,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from '@app/shared/components/
ThemeSelectorComponent,
RateUnitSelectorComponent,
AmountSelectorComponent,
+ TimezoneSelectorComponent,
ScriptpubkeyTypePipe,
RelativeUrlPipe,
NoSanitizePipe,
@@ -283,6 +285,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from '@app/shared/components/
RateUnitSelectorComponent,
ThemeSelectorComponent,
AmountSelectorComponent,
+ TimezoneSelectorComponent,
ScriptpubkeyTypePipe,
RelativeUrlPipe,
Hex2asciiPipe,