немецкий формат даты для средства выбора даты ng-bootstrap

Мне нужна ваша помощь, используя NgbDateParserFormatter для средства выбора даты ng-bootstrap. Мне нужен немецкий формат дд.мм.гггг (например, 31.03.2017).

У меня есть плункер, но он работает некорректно:

  • выбор некоторых дат работы (например, выбор 17.03.2017 приводит к 17.03.2017)
  • выбор некоторых дат не работает (выбор 02.09.1937 приводит к 01.09.1937)
  • ввод даты меняет местами день и месяц (01.03.2017 получает 03.01.2017, а 14.03.2017 получает пустой ввод из-за отсутствия 03.14.2017)

Вот код:

import { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
import { DatePipe } from '@angular/common';

export class CustomNgbDateParserFormatter extends NgbDateParserFormatter {
    datePipe = new DatePipe('de-AT');
    constructor(
        private dateFormatString: string) {
        super();
    }
    format(date: NgbDateStruct): string {
        if (date === null) {
            return '';
        }
        try {
            return this.datePipe.transform(new Date(date.year, date.month - 1, date.day), this.dateFormatString);
        } catch (e) {
            return '';
        }
    }
    parse(value: string): NgbDateStruct {
        let returnVal: NgbDateStruct;
        if (!value) {
            returnVal = null;
        } else {
            try {
                let dateParts = this.datePipe.transform(value, 'M-d-y').split('-');
                returnVal = { year: parseInt(dateParts[2]), month: parseInt(dateParts[0]), day: parseInt(dateParts[1]) };
            } catch (e) {
                returnVal = null;
            }
        }
        return returnVal;
    }
}

Не могли бы вы мне помочь, пожалуйста?

Большое спасибо за Вашу помощь.


person kanlo    schedule 29.03.2017    source источник


Ответы (3)


Вы усложняете себе жизнь, используя объекты JS Date и класс DatePipe. Это проблематично по следующим причинам:

  • Date Объекты JS несут информацию о времени и часовом поясе, поэтому, не проявляя осторожности, вы можете легко столкнуться с проблемами, связанными с преобразованием часового пояса - именно поэтому ng-bootstrap использует выделенные структуры данных.
  • DataPipe использует Intl API под капотом, и, к сожалению, он довольно глючный.

Хорошей новостью является то, что вы можете легко реализовать желаемую функциональность, следуя синтаксическому анализатору/форматеру ISO, как показано здесь: /ngb-date-parser-formatter.ts#L25-L45" rel="nofollow noreferrer">https://github.com/ng-bootstrap/ng-bootstrap/blob/088363551b5d5ecd602a82aedfc97d43a75a080f/src/datepicker/ngb-date- parser-formatter.ts#L25-L45

Если я правильно понимаю ваше намерение, ваш код может выглядеть следующим образом:

export class CustomNgbDateParserFormatter extends NgbDateParserFormatter {

    format(date: NgbDateStruct): string {
      return date ? `${padNumber(date.month)}.${padNumber(date.day)}.${date.year}` : '';
    }

    parse(value: string): NgbDateStruct {
        if (value) {
      const dateParts = value.trim().split('.');
      if (dateParts.length === 1 && isNumber(dateParts[0])) {
        return {year: null, month: toInteger(dateParts[0]), day: null};
      } else if (dateParts.length === 2 && isNumber(dateParts[0]) && isNumber(dateParts[1])) {
        return {year: null, month: toInteger(dateParts[0]), day: toInteger(dateParts[1])};
      } else if (dateParts.length === 3 && isNumber(dateParts[0]) && isNumber(dateParts[1]) && isNumber(dateParts[2])) {
        return {year: toInteger(dateParts[2]), month: toInteger(dateParts[0]), day: toInteger(dateParts[1])};
      }
    }
    return null;
    }
}

Вот плункер, показывающий это в действии: https://plnkr.co/edit/JdX0eHcl7QddOWxM9aT0?p=preview

person pkozlowski.opensource    schedule 29.03.2017
comment
Большое спасибо за ваш ответ, но выбор даты с помощью курсора приводит к дате, в которой день и месяц меняются местами. Ввод даты позволяет дате быть правильной. - person kanlo; 29.03.2017
comment
@kanlo Я думал, что вы ориентируетесь на формат месяц-день-год, и это то, что реализовано в связанном плункере, нет? В любом случае, если вы стремитесь к другому формату, адаптировать код, который я связал, должно быть тривиально. - person pkozlowski.opensource; 29.03.2017

В основном это ответ pkozlowski.opensource, но месяц/день заменены местами, поскольку это общий формат в Германии.

import { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
import { DatePipe } from '@angular/common';

function padNumber(value: number) {
    if (isNumber(value)) {
        return `0${value}`.slice(-2);
    } else {
        return '';
    }
}

function toInteger(value: any): number {
    return parseInt(`${value}`, 10);
}

function isNumber(value: any): boolean {
    return !isNaN(toInteger(value));
}

export class CustomNgbDateParserFormatter extends NgbDateParserFormatter {

    format(date: NgbDateStruct): string {
        return date ? `${padNumber(date.day)}.${padNumber(date.month)}.${date.year}` : '';
    }

    parse(value: string): NgbDateStruct {
        if (value) {
            const dateParts = value.trim().split('.');
            if (dateParts.length === 1 && isNumber(dateParts[0])) {
                return { year: null, day: toInteger(dateParts[0]), month: null };
            } else if (dateParts.length === 2 && isNumber(dateParts[0]) && isNumber(dateParts[1])) {
                return { year: null, day: toInteger(dateParts[0]), month: toInteger(dateParts[1]) };
            } else if (dateParts.length === 3 && isNumber(dateParts[0]) && isNumber(dateParts[1]) && isNumber(dateParts[2])) {
                return { year: toInteger(dateParts[2]), day: toInteger(dateParts[0]), month: toInteger(dateParts[1]) };
            }
        }
        return null;
    }
}
person assemble me    schedule 11.06.2018

Вот мое решение, надеюсь, оно вам поможет. Чтобы это работало, вы должны сделать запись в app.module.ts следующим образом:

providers: [...,
{ provide: NgbDateParserFormatter, useClass: NgbDateFRParserFormatter }]

Вы выбираете дату из средства выбора даты или вводите дату вручную, она автоматически преобразует ее формат в дд.ММ.гггг.

import { Injectable, Inject } from '@angular/core';
import { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';


@Injectable()
export class NgbDateFRParserFormatter extends NgbDateParserFormatter {

parse(value: string): NgbDateStruct {
if (value) {
  const dateParts = value.trim().split('/');
  if (dateParts.length === 1 && isNumber(dateParts[0])) {
    return { year: toInteger(dateParts[0]), month: null, day: null };
  } else if (
    dateParts.length === 2 &&
    isNumber(dateParts[0]) &&
    isNumber(dateParts[1])
  ) {
    return {
      year: toInteger(dateParts[1]),
      month: toInteger(dateParts[0]),
      day: null
    };
  } else if (
    dateParts.length === 3 &&
    isNumber(dateParts[0]) &&
    isNumber(dateParts[1]) &&
    isNumber(dateParts[2])
  ) {
    return {
      year: toInteger(dateParts[2]),
      month: toInteger(dateParts[1]),
      day: toInteger(dateParts[0])
    };
  }
}
 return null;
}


format(date: NgbDateStruct): string {
let stringDate = '';
const language = this.authService.getUser().language;

  if (date) {
    stringDate += isNumber(date.day) ? padNumber(date.day) + '.' : '';
    stringDate += isNumber(date.month) ? padNumber(date.month) + '.' : '';
    stringDate += date.year;
  }
   return stringDate;
  }
 }

 function padNumber(value: number) {
  if (isNumber(value)) {
  return `0${value}`.slice(-2);
 } else {
  return '';
 }
}

 function isNumber(value: any): boolean {
   return !isNaN(toInteger(value));
}

   function toInteger(value: any): number {
   return parseInt(`${value}`, 10);
  }
person Rahul Singh    schedule 02.07.2018