"file-saver": "^2.0.2",
"material-design-icons": "^3.0.1",
"moment": "2.24.0",
- "moment-timezone": "0.5.23",
+ "moment-timezone": "^0.5.26",
"ngx-cookie": "^4.1.2",
"rxjs": "^6.5.2",
"zone.js": "^0.8.29"
import {Injectable, Pipe, PipeTransform} from '@angular/core';
-import {DatePipe, CurrencyPipe} from '@angular/common';
+import {DatePipe, CurrencyPipe, getLocaleDateFormat, getLocaleTimeFormat, getLocaleDateTimeFormat, FormatWidth} from '@angular/common';
import {IdlService, IdlObject} from '@eg/core/idl.service';
import {OrgService} from '@eg/core/org.service';
+import {LocaleService} from '@eg/core/locale.service';
import * as Moment from 'moment-timezone';
/**
private datePipe: DatePipe,
private currencyPipe: CurrencyPipe,
private idl: IdlService,
- private org: OrgService
+ private org: OrgService,
+ private locale: LocaleService
) {
// Create an inilne polyfill for Number.isNaN, which is
*
* Returns a blank string if it can't do this transformation.
*/
- private makeFormatParseable(original: string): string {
+ private makeFormatParseable(original: string, locale?: string): string {
if (!original) { return ''; }
+ if (!locale) { locale = locale; }
switch (original) {
case 'short': {
- return 'M/D/YY, h:mm a';
+ const template = getLocaleDateTimeFormat(locale, FormatWidth.Short);
+ const date = getLocaleDateFormat(locale, FormatWidth.Short);
+ const time = getLocaleTimeFormat(locale, FormatWidth.Short);
+ original = template
+ .replace('{1}', date)
+ .replace('{0}', time)
+ .replace(/\'(\w+)\'/, '[$1]');
+ break;
}
case 'medium': {
- return 'MMM D, Y, h:mm:ss a';
+ const template = getLocaleDateTimeFormat(locale, FormatWidth.Medium);
+ const date = getLocaleDateFormat(locale, FormatWidth.Medium);
+ const time = getLocaleTimeFormat(locale, FormatWidth.Medium);
+ original = template
+ .replace('{1}', date)
+ .replace('{0}', time)
+ .replace(/\'(\w+)\'/, '[$1]');
+ break;
}
case 'long': {
- return 'MMMM D, Y, h:mm:ss a [GMT]Z';
+ const template = getLocaleDateTimeFormat(locale, FormatWidth.Long);
+ const date = getLocaleDateFormat(locale, FormatWidth.Long);
+ const time = getLocaleTimeFormat(locale, FormatWidth.Long);
+ original = template
+ .replace('{1}', date)
+ .replace('{0}', time)
+ .replace(/\'(\w+)\'/, '[$1]');
+ break;
}
case 'full': {
- return 'dddd, MMMM D, Y, h:mm:ss a [GMT]Z';
+ const template = getLocaleDateTimeFormat(locale, FormatWidth.Full);
+ const date = getLocaleDateFormat(locale, FormatWidth.Full);
+ const time = getLocaleTimeFormat(locale, FormatWidth.Full);
+ original = template
+ .replace('{1}', date)
+ .replace('{0}', time)
+ .replace(/\'(\w+)\'/, '[$1]');
+ break;
}
case 'shortDate': {
- return 'M/D/YY';
+ original = getLocaleDateFormat(locale, FormatWidth.Short);
+ break;
}
case 'mediumDate': {
- return 'MMM D, Y';
+ original = getLocaleDateFormat(locale, FormatWidth.Medium);
+ break;
}
case 'longDate': {
- return 'MMMM D, Y';
+ original = getLocaleDateFormat(locale, FormatWidth.Long);
+ break;
}
case 'fullDate': {
- return 'dddd, MMMM D, Y';
+ original = getLocaleDateFormat(locale, FormatWidth.Full);
+ break;
}
case 'shortTime': {
- return 'h:mm a';
+ original = getLocaleTimeFormat(locale, FormatWidth.Short);
+ break;
}
case 'mediumTime': {
- return 'h:mm:ss a';
+ original = getLocaleTimeFormat(locale, FormatWidth.Medium);
+ break;
}
case 'longTime': {
- return 'h:mm:ss a [GMT]Z';
+ original = getLocaleTimeFormat(locale, FormatWidth.Long);
+ break;
}
case 'fullTime': {
- return 'h:mm:ss a [GMT]Z';
+ original = getLocaleTimeFormat(locale, FormatWidth.Full);
+ break;
}
}
return original
return this.formatter.transform({value: value, datatype: datatype});
}
}
-
-import {DatePipe, CurrencyPipe} from '@angular/common';
+import {DatePipe, CurrencyPipe, registerLocaleData} from '@angular/common';
import {IdlService} from './idl.service';
import {EventService} from './event.service';
import {NetService} from './net.service';
import {PcrudService} from './pcrud.service';
import {StoreService} from './store.service';
import {OrgService} from './org.service';
+import {LocaleService} from './locale.service';
+import {Location} from '@angular/common';
import {FormatService} from './format.service';
-
+import {SpyLocation} from '@angular/common/testing';
+import localeArJO from '@angular/common/locales/ar-JO';
+import localeCs from '@angular/common/locales/cs';
+import localeFrCA from '@angular/common/locales/fr-CA';
describe('FormatService', () => {
let orgService: OrgService;
let evtService: EventService;
let storeService: StoreService;
+ let localeService: LocaleService;
+ // tslint:disable-next-line:prefer-const
+ let location: SpyLocation;
let service: FormatService;
beforeEach(() => {
authService = new AuthService(evtService, netService, storeService);
pcrudService = new PcrudService(idlService, netService, authService);
orgService = new OrgService(netService, authService, pcrudService);
+ localeService = new LocaleService(location, null, pcrudService);
service = new FormatService(
datePipe,
currencyPipe,
idlService,
- orgService
+ orgService,
+ localeService
);
});
const momentVersion = service['makeFormatParseable']('MMMM d, y, h:mm:ss a z');
expect(momentVersion).toBe('MMMM D, Y, h:mm:ss a [GMT]Z');
});
- it('should transform full Angular format strings to a valid MomentJS one', () => {
- const momentVersion = service['makeFormatParseable']('full');
- expect(momentVersion).toBe('dddd, MMMM D, Y, h:mm:ss a [GMT]Z');
+ it('should transform full Angular format strings to a valid MomentJS one using Angular locale en-US', () => {
+ const momentVersion = service['makeFormatParseable']('full', 'en-US');
+ expect(momentVersion).toBe('dddd, MMMM D, Y [at] h:mm:ss a [GMT]Z');
+ });
+ it('should transform shortDate Angular format strings to a valid MomentJS one using Angular locale cs-CZ', () => {
+ registerLocaleData(localeCs);
+ const momentVersion = service['makeFormatParseable']('shortDate', 'cs-CZ');
+ expect(momentVersion).toBe('DD.MM.YY');
+ });
+ it('should transform mediumDate Angular format strings to a valid MomentJS one using Angular locale fr-CA', () => {
+ registerLocaleData(localeFrCA);
+ const momentVersion = service['makeFormatParseable']('mediumDate', 'fr-CA');
+ expect(momentVersion).toBe('D MMM Y');
+ });
+ it('should transform long Angular format strings to a valid MomentJS one using Angular locale ar-JO', () => {
+ registerLocaleData(localeArJO);
+ const momentVersion = service['makeFormatParseable']('long', 'ar-JO');
+ expect(momentVersion).toBe('D MMMM Y h:mm:ss a [GMT]Z');
});
it('can create a valid Momentjs object given a valid datetime string and correct format', () => {
const moment = service['momentize']('7/3/12, 6:06 PM', 'M/D/YY, h:mm a', 'Africa/Addis_Ababa', false);
import {NgbDate} from '@ng-bootstrap/ng-bootstrap';
@Component({
+ // tslint:disable-next-line:component-selector
selector: 'ngb-datepicker',
template: ''
})
[formGroup]="dateTimeForm"
class="input-group"
ngbDropdown
- [autoClose]="false"
+ [autoClose]="'outside'"
#dt="ngbDropdown">
<input type="datetime"
[attr.id]="domId.length ? domId : null"
@Self()
public controlDir: NgControl, // so that the template can access validation state
) {
- controlDir.valueAccessor = this;
+ if (controlDir) { controlDir.valueAccessor = this; }
this.onChangeAsIso = new EventEmitter<string>();
const startValue = Moment.tz([], this.timezone);
this.dateTimeForm = new FormGroup({
selector: '[egValidDatetime]',
providers: [{
provide: NG_VALIDATORS,
- useExisting: forwardRef(() => DatetimeValidator),
+ useExisting: DatetimeValidatorDirective,
multi: true
}]
})
</form>
</div>
</div>
+<label for="date-time-input">
+ Set the datetime and timezone library settings, and enter a valid datetime string for an exciting animation surprise:
+</label>
+<input id="date-time-input" type="text" class="date-time-input" ngModel egValidDatetime required>
<br/><br/>
<h4>Grid with filtering</h4>
import * as Moment from 'moment-timezone';
@Component({
- templateUrl: 'sandbox.component.html'
+ templateUrl: 'sandbox.component.html',
+ styles: ['.date-time-input.ng-invalid {border: 5px purple solid;}',
+ '.date-time-input.ng-valid {border: 5px green solid; animation: slide 5s linear 1s infinite alternate;}',
+ '@keyframes slide {0% {margin-left:0px;} 50% {margin-left:200px;}']
})
export class SandboxComponent implements OnInit {