import {DatePipe, DecimalPipe, getLocaleDateFormat, getLocaleTimeFormat, getLocaleDateTimeFormat, FormatWidth} from '@angular/common';
import {IdlService, IdlObject} from '@eg/core/idl.service';
import {OrgService} from '@eg/core/org.service';
+import {AuthService} from '@eg/core/auth.service';
import {LocaleService} from '@eg/core/locale.service';
import * as moment from 'moment-timezone';
+import {DateUtil} from '@eg/share/util/date';
/**
* Format IDL vield values for display.
orgField?: string; // 'shortname' || 'name'
datePlusTime?: boolean;
timezoneContextOrg?: number;
+ dateOnlyInterval?: string;
}
@Injectable({providedIn: 'root'})
dateFormat = 'shortDate';
dateTimeFormat = 'short';
wsOrgTimezone: string = OpenSRF.tz;
+ tzCache: {[orgId: number]: string} = {};
constructor(
private datePipe: DatePipe,
private decimalPipe: DecimalPipe,
private idl: IdlService,
private org: OrgService,
+ private auth: AuthService,
private locale: LocaleService
) {
// local one
tz = 'UTC';
} else {
- tz = this.wsOrgTimezone;
+ if (params.timezoneContextOrg) {
+ tz = this.getOrgTz( // support ID or object
+ this.org.get(params.timezoneContextOrg).id());
+ } else {
+ tz = this.wsOrgTimezone;
+ }
}
+
const date = moment(value).tz(tz);
- if (!date.isValid()) {
- console.error('Invalid date in format service', value);
+ if (!date || !date.isValid()) {
+ console.error(
+ 'Invalid date in format service; date=', value, 'tz=', tz);
return '';
}
+
let fmt = this.dateFormat || 'shortDate';
+
if (params.datePlusTime) {
+ // Time component directly requested
fmt = this.dateTimeFormat || 'short';
+
+ } else if (params.dateOnlyInterval) {
+ // Time component displays for non-day-granular intervals.
+ const secs = DateUtil.intervalToSeconds(params.dateOnlyInterval);
+ if (secs !== null && secs % 86400 !== 0) {
+ fmt = this.dateTimeFormat || 'short';
+ }
}
+
return this.datePipe.transform(date.toISOString(true), fmt, date.format('ZZ'));
case 'money':
return value + '';
}
}
+
+ /**
+ Fetch the org timezone from cache when available. Otherwise,
+ get the timezone from the org unit setting. The first time
+ this call is made, it may return the incorrect value since
+ it's not a promise-returning method (because format() is not a
+ promise-returning method). Future calls will return the correct
+ value since it's locally cached. Since most format() calls are
+ repeated many times for Angular digestion, the end result is that
+ the correct value will be used in the end.
+ */
+ getOrgTz(orgId: number): string {
+
+ if (this.tzCache[orgId] === null) {
+ // We are still waiting for the value to be returned
+ // from the server.
+ return this.wsOrgTimezone;
+ }
+
+ if (this.tzCache[orgId] !== undefined) {
+ // We have a cached value.
+ return this.tzCache[orgId];
+ }
+
+ // Avoid duplicate parallel lookups by indicating we
+ // are loading the value from the server.
+ this.tzCache[orgId] = null;
+
+ this.org.settings(['lib.timezone'], orgId)
+ .then(sets => this.tzCache[orgId] = sets['lib.timezone']);
+
+ // Use the local timezone while we wait for the real value
+ // to load from the server.
+ return this.wsOrgTimezone;
+ }
+
/**
* Create an IDL-friendly display version of a human-readable date
*/
}
}
+@Pipe({name: 'egOrgDateInContext'})
+export class OrgDateInContextPipe implements PipeTransform {
+ constructor(private formatter: FormatService) {}
+
+ transform(value: string, orgId?: number, interval?: string ): string {
+ return this.formatter.transform({
+ value: value,
+ datatype: 'timestamp',
+ timezoneContextOrg: orgId,
+ dateOnlyInterval: interval
+ });
+ }
+}
+
+@Pipe({name: 'egDueDate'})
+export class DueDatePipe implements PipeTransform {
+ constructor(private formatter: FormatService) {}
+
+ transform(circ: IdlObject): string {
+ return this.formatter.transform({
+ value: circ.due_date(),
+ datatype: 'timestamp',
+ timezoneContextOrg: circ.circ_lib(),
+ dateOnlyInterval: circ.duration()
+ });
+ }
+}
+