角 2 "time ago"管



我正试图为我的Angular 2应用程序创建一个"很久以前"的管道。

它应该将日期转换为字符串,例如"5分钟前"或"60秒前"。到目前为止,它运行得很好,但在第一次计算后不会更新。例如,如果给定日期是5秒前,则显示"5秒前",但此后不会更改。

我已经尝试过将管道的"纯"值设置为false,但这没有帮助。

这是我的代码:

import {Pipe, PipeTransform} from 'angular2/core';
@Pipe({
  name: 'messageTime',
  pure: false
})
export class MessageTimePipe implements PipeTransform {
  transform(value: Date, []): string {
    var result: string;
    // current time
    let now = new Date().getTime();
    // time since message was sent in seconds
    let delta = (now - value.getTime()) / 1000;
    // format string
    if (delta < 10) {
      result = 'jetzt';
    } else if (delta < 60) { // sent in last minute
      result = 'vor ' + Math.floor(delta) + ' Sekunden';
    } else if (delta < 3600) { // sent in last hour
      result = 'vor ' + Math.floor(delta / 60) + ' Minuten';
    } else if (delta < 86400) { // sent on last day
      result = 'vor ' + Math.floor(delta / 3600) + ' Stunden';
    } else { // sent more than one day ago
      result = 'vor ' + Math.floor(delta / 86400) + ' Tagen';
    }
    return result;
  }
}

我使用的过滤器是这样的:

TypeScript:

import {Component, Input} from 'angular2/core';
import {MessageTimePipe} from '../../pipes/message-time.pipe';
@Component({
  selector: 'message-item',
  pipes: [MessageTimePipe],
  templateUrl: 'build/components/message-item/message-item.component.html'
})
export class MessageItemComponent {
  @Input()
  message: JSON;
  date: Date;
  ngOnInit() {
   this.date = new Date(2016, 3, 16, 12, 49, 10);
  }
}

HTML:

<p class="time">
  {{ date | messageTime }}
</p>

以下库在英语中起着同等的作用,可以分叉以更改语言或支持不同的语言:

https://www.npmjs.com/package/time-ago-pipe

npm install time-ago-pipe --save

然后在@NgModule中,你想在中使用它

import {TimeAgoPipe} from 'time-ago-pipe'
@NgModule({
    imports: [... etc ...],
    declarations: [AppComponent, ...etc..., TimeAgoPipe],
    bootstrap: [AppComponent]
})

在模板中:

<span>{{your_date | timeAgo}}</span>

终于开始工作了,这很有挑战性,需要调整间隔:)

import {Pipe, ChangeDetectorRef} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import {AsyncPipe} from 'angular2/common';
@Pipe({
    name: 'messageTime',
    pure: false
})
export class MessageTimePipe extends AsyncPipe
{
    value:Date;
    timer:Observable<string>;
    constructor(ref:ChangeDetectorRef)
    {
        super(ref);
    }
    transform(obj:any, args?:any[]):any
    {
        if (obj instanceof Date)
        {
            this.value = obj;
            if(!this.timer)
            {
                this.timer = this.getObservable();
            }
            return super.transform(this.timer, args);
        }
        return super.transform(obj, args);
    }
    private getObservable()
    {
        return Observable.interval(1000).startWith(0).map(()=>
        {
            var result:string;
            // current time
            let now = new Date().getTime();
            // time since message was sent in seconds
            let delta = (now - this.value.getTime()) / 1000;
            // format string
            if (delta < 10)
            {
                result = 'jetzt';
            }
            else if (delta < 60)
            { // sent in last minute
                result = 'vor ' + Math.floor(delta) + ' Sekunden';
            }
            else if (delta < 3600)
            { // sent in last hour
                result = 'vor ' + Math.floor(delta / 60) + ' Minuten';
            }
            else if (delta < 86400)
            { // sent on last day
                result = 'vor ' + Math.floor(delta / 3600) + ' Stunden';
            }
            else
            { // sent more than one day ago
                result = 'vor ' + Math.floor(delta / 86400) + ' Tagen';
            }
            return result;
        });
    };
}

使用ngx矩https://github.com/urish/ngx-moment,与Momentjs的管道集成,i18n支持

接受的答案无法使用angular 7+。

我遵循了这个答案,并为越南人定制。

https://stackoverflow.com/a/61341940/4964569

我和谁一样关心。

import {Pipe, PipeTransform} from '@angular/core';
    @Pipe({
        name: 'dateAgo',
        pure: true
    })
    export class TimePipe implements PipeTransform {
    
        transform(value: any, args?: any): any {
            if (value) {
                const seconds = Math.floor((+new Date() - +new Date(value)) / 1000);
                if (seconds < 29) // less than 30 seconds ago will show as 'Just now'
                    return 'vừa mới đăng';
                const intervals = {
                    'năm': 31536000,
                    'tháng': 2592000,
                    'tuần': 604800,
                    'ngày': 86400,
                    'giờ': 3600,
                    'phút': 60,
                    'giây': 1
                };
                let counter;
                for (const i in intervals) {
                    counter = Math.floor(seconds / intervals[i]);
                    if (counter > 0){
                      return counter + ' ' + i + ' trước'; // singular (1 day ago)
                    }
                }
            }
            return value;
        }
    }

我认为这与管道无关,而是与Angular2检测更改的方式有关。它检测基于引用的更改,即绑定引用是否更改,而不是其中的元素是否更新。

参见以下示例:

@Component({
  selector: 'my-app',
  template: `
    <div>{{val | pdate}}</div>
  `,
  pipes: [ DatePipe ]
})
export class AppComponent {
  constructor() {
    this.val = new Date();
    setTimeout(() => {
      this.val = new Date(); // Updates view
    }, 1000);
    setTimeout(() => {
      this.val.setTime((new Date().getTime()); // Doesn't update view
    }, 2000);
  }
}

参见thisx plunkr:https://plnkr.co/edit/kJdi1wx0iu9tDx8yTmRx?p=preview.

正如Thierry所指出的,您需要更新"日期"引用来触发Angular2的更改检测,例如使用setTimeout(()=>this.date=new Date(), period)

你真的需要每秒钟更新一次吗?根据您的用例,每60秒更新一次可能就足够了,并且在前60秒可能显示"刚刚"或"不到一分钟前"。

但如果你真的想要这几秒钟,你只需要在前60秒内每秒钟更新一次。setTimeout(1000)然后可以变成setTimeout(60000),以最小化开销。

moment.js解决方案。在Angular 6:中工作/测试

import { ChangeDetectorRef, NgZone, Pipe, PipeTransform } from '@angular/core';
import * as moment from 'moment';
moment.locale("de"); // set your language
@Pipe({
    name:'timeago',
    pure:false
})
export class TimeagoPipe implements PipeTransform {    
    private timer: number;
    constructor(private changeDetectorRef: ChangeDetectorRef, private ngZone: NgZone) {}
    transform(value:string) {
        this.removeTimer();
        let d = new Date(value);
        let now = new Date();
        let seconds = Math.round(Math.abs((now.getTime() - d.getTime())/1000));
        let timeToUpdate = (Number.isNaN(seconds)) ? 1000 : this.getSecondsUntilUpdate(seconds) *1000;
        this.timer = this.ngZone.runOutsideAngular(() => {
            if (typeof window !== 'undefined') {
                return window.setTimeout(() => {
                    this.ngZone.run(() => this.changeDetectorRef.markForCheck());
                }, timeToUpdate);
            }
            return null;
        });
    return moment(d).fromNow();
    }
    ngOnDestroy(): void {
        this.removeTimer();
    }
    private removeTimer() {
        if (this.timer) {
            window.clearTimeout(this.timer);
            this.timer = null;
        }
    }
    private getSecondsUntilUpdate(seconds:number) {
        let min = 60;
        let hr = min * 60;
        let day = hr * 24;
        if (seconds < min) { // less than 1 min, update every 2 secs
            return 2;
        } else if (seconds < hr) { // less than an hour, update every 30 secs
            return 30;
        } else if (seconds < day) { // less then a day, update every 5 mins
            return 300;
        } else { // update every hour
            return 3600;
        }
    }
}

在AngularJs2中获取时间Ago

您需要运行以下命令npm install time ago pipe-save才能在您的angular应用程序中安装time ago npm软件包例如:PS D:\D\TimeAgo>npm install time ago pipe--save运行此命令后,将添加包。图显示如何从"时间管道"添加导入{TimeAgoPipe};在app.module中,并将TimeAgoPipe放入Declarations中[从componento传递输入/p

最新更新