Giter Site home page Giter Site logo

timeago.dart's Introduction

timeago

timeago is a dart library that converts a date into a humanized text. Instead of showing a date 2020-12-12 18:30 with timeago you can display something like "now", "an hour ago", "~1y", etc

timeago pub package core library
timeago_flutter pub package flutter widgets

The easiest way to use this library via top-level function format(date):

import 'package:timeago/timeago.dart' as timeago;

main() {
    final fifteenAgo = DateTime.now().subtract(Duration(minutes: 15));

    print(timeago.format(fifteenAgo)); // 15 minutes ago
    print(timeago.format(fifteenAgo, locale: 'en_short')); // 15m
    print(timeago.format(fifteenAgo, locale: 'es')); // hace 15 minutos
}
IMPORTANT

timeago library ONLY includes en and es messages loaded by default.

To add more of the supported languages use timeago.setLocaleMessages(..). See locale messages.

Standard for language code

This library uses ISO 639-1 language code to identify the language. For more information see ISO 639-1.

Adding locales

timeago.setLocaleMessages('fr', timeago.FrMessages()); // Add french messages

print(timeago.format(fifteenAgo, locale: 'es')); // environ 15 minutes

Overriding locales or adding custom messages

// Override "en" locale messages with custom messages that are more precise and short
timeago.setLocaleMessages('en', MyCustomMessages());


// my_custom_messages.dart
class MyCustomMessages implements LookupMessages {
  @override String prefixAgo() => '';
  @override String prefixFromNow() => '';
  @override String suffixAgo() => '';
  @override String suffixFromNow() => '';
  @override String lessThanOneMinute(int seconds) => 'now';
  @override String aboutAMinute(int minutes) => '${minutes}m';
  @override String minutes(int minutes) => '${minutes}m';
  @override String aboutAnHour(int minutes) => '${minutes}m';
  @override String hours(int hours) => '${hours}h';
  @override String aDay(int hours) => '${hours}h';
  @override String days(int days) => '${days}d';
  @override String aboutAMonth(int days) => '${days}d';
  @override String months(int months) => '${months}mo';
  @override String aboutAYear(int year) => '${year}y';
  @override String years(int years) => '${years}y';
  @override String wordSeparator() => ' ';
}

Scope

While there are many request for adding more complex functionality I want keep this library as simple as possible to allow minimal maintenance.

The focus of this library should be

  1. Provide a single format function that transforms a date to a humanized value
  2. Give the abstractions for users to add their own languages or overriding them as they please
  3. Provide languages contributed by the community so users can add them as they need we should not add all languages by default.
  4. Library should not depend on any dependency

timeago_flutter widgets

  • Timeago
  • TimerRefresh
  • TimerRefreshWidget

Local development

  1. Install Melos (https://pub.dev/packages/melos):

dart pub global activate melos

  1. Bootstrap dependencies:

melos bootstrap

  1. Open desired package in VSCode or Webstorm

Live Demo

Here

timeago.dart's People

Contributors

admirhusic avatar alexnikitchuk avatar altotunchitoo avatar ammaratef45 avatar andresaraujo avatar bachvtuan avatar bipinct avatar btastic avatar comlaterra avatar dehypnosis avatar dharisd avatar elvander avatar enyo avatar glacials avatar goolpe avatar igdmitrov avatar kesoji avatar kranfix avatar luantranminh avatar mchudy avatar mominraza avatar nikolajskov avatar skybur avatar suusojeat avatar tlindi avatar vbuberen avatar vincentderidder avatar xoshbin avatar yshwork avatar zirho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

timeago.dart's Issues

Can you add MS (Malay Malaysian) Languange

import 'package:timeago/src/messages/lookupmessages.dart';

class MsMessages implements LookupMessages {
  @override
  String prefixAgo() => '';
  @override
  String prefixFromNow() => '';
  @override
  String suffixAgo() => 'lepas';
  @override
  String suffixFromNow() => 'dari sekarang';
  @override
  String lessThanOneMinute(int seconds) => 'saat';
  @override
  String aboutAMinute(int minutes) => 'seminit';
  @override
  String minutes(int minutes) => '$minutes minit';
  @override
  String aboutAnHour(int minutes) => 'sejam';
  @override
  String hours(int hours) => '$hours jam';
  @override
  String aDay(int hours) => 'sehari';
  @override
  String days(int days) => '$days hari';
  @override
  String aboutAMonth(int days) => 'sebulan';
  @override
  String months(int months) => '$months bulan';
  @override
  String aboutAYear(int year) => 'setahun';
  @override
  String years(int years) => '$years tahun';
  @override
  String wordSeparator() => ' ';
}

class EnShortMessages implements LookupMessages {
  @override
  String prefixAgo() => '';
  @override
  String prefixFromNow() => '';
  @override
  String suffixAgo() => '';
  @override
  String suffixFromNow() => '';
  @override
  String lessThanOneMinute(int seconds) => 'sekarang';
  @override
  String aboutAMinute(int minutes) => '1 min';
  @override
  String minutes(int minutes) => '$minutes min';
  @override
  String aboutAnHour(int minutes) => '~1 jam';
  @override
  String hours(int hours) => '$hours jam';
  @override
  String aDay(int hours) => '~1 hri';
  @override
  String days(int days) => '$days hri';
  @override
  String aboutAMonth(int days) => '~1 bln';
  @override
  String months(int months) => '$months bln';
  @override
  String aboutAYear(int year) => '~1 thn';
  @override
  String years(int years) => '$years thn';
  @override
  String wordSeparator() => ' ';
}

Future Dates

If I give a date in future e.g. 15 days from now what is returned is a moment ago. I would expect in 15 days like the moment.js lib

Testability: Allow a fake `new DateTime.now()`

Idea:

class TimeAgo {
  TimeAgo({String locale, DateTime Function() clock}) {
    this.locale = locale;
    this.clock = clock ?? () => new DateTime.now();
  }

  // ... and use clock below ...
}

If you agree with this, let me know, and I can send a PR :)

Can I use limit?

Hi
it's so wonderful
but I want set range

for example

Before 7days => 5m, 7days ago (etc..)
After 7days => 2020-03-26 08:13, 2020-03-26 (or some other format)

Can I ?

Clock variable is not working

I'm trying to compare time to UTC by passing UTC date but it still take the time from mobile timezone
Here is the test

DateTime utcDate = DateTime.now().toUtc();
DateTime serverDate = DateTime.parse(myEntity.publishDate);
print("utc date: $utcDate");
print("server date: $serverDate");
print("app timezone date: ${DateTime.now()}");
print("format: ${timeago.format(serverDate, locale: "en",clock: utcDate)}");

and here is the result

utc date: 2019-11-11 15:47:07.547533Z
server date: 2019-11-11 15:15:11.626
app timezone date: 2019-11-11 18:47:07.547691
format: 4 hours ago

multi language does not work

multi-language does not work and returns only English.

in src\timeago.dat please add other languages. (now added en and es only)

Map<String, LookupMessages> _lookupMessagesMap = {
'en': EnMessages(),
'en_short': EnShortMessages(),
'es': EsMessages(),
'es_short': EsShortMessages(),
'fr': FrMessages(),
};

I added fr language.

Add me as a maintainer

Please, the package need maintenance for supporting more features and I've sent an approved PR before and another in pending state.

There are many god contributions and I can maintain this package.

Unclear, which language code standard is used

Please, add to readme some ISO link or whatever, because it's unclear which standard is used
I were going to add Ukrainian translation, but it uses uk and ua codes in different standards

timeago

timeago is not working in flutter in vs code

pt_BR localizations

Just a friendly reminder to myself to create a PR to add this.

(or if anyone does it first).

pt_BR seems to be not working

I tested the new locale 'pt_BR' but it still showing the default english locale...

timeAgo(date, locale: 'pt_BR')
is showing '21 hours ago'

I confirmed it is getting from the last release

Can you please confirm the pt_BR is working properly ? Thanks.

Change request for JaMessages class

Japanese counter characters for number of months is complex. See : HOW TO USE THE JAPANESE COUNTER 箇月 (かげつ)

But using hiragana ‘か’ instead of ‘個’ is most common. I think expressing like ‘か月’ for number of month(s) is the best fit for contemporary Japanese.

Please replace ‘月’ with ‘か月’ in the line 15 and 16 of the file : timeago.dart/timeago/lib/src/messages/ja_messages.dart
as :

import 'package:timeago/src/messages/lookupmessages.dart';

class JaMessages implements LookupMessages {
String prefixAgo() => '';
String prefixFromNow() => '今から';
String suffixAgo() => '前';
String suffixFromNow() => '後';
String lessThanOneMinute(int seconds) => '1 分未満e';
String aboutAMinute(int minutes) => '約 1 分';
String minutes(int minutes) => '$minutes 分';
String aboutAnHour(int minutes) => '約 1 時間';
String hours(int hours) => '約 $hours 時間';
String aDay(int hours) => '約 1 日';
String days(int days) => '約 ${days} 日';
String aboutAMonth(int days) => '約 1 か月';
String months(int months) => '約 ${months} か月';
String aboutAYear(int year) => '約 1 年';
String years(int years) => '約 ${years} 年';
String wordSeparator() => ' ';
}

More resolution for times under a minute

Instead of always saying, "just a moment ago" for anything under one minute, can it break up that period into several different texts?

When showing the progress of an activity, the user might think nothing is happening if it always said the same thing for the first minute. They are going to get impatient if nothing changes before a minute. Or the text is not going to be useful if the task only takes about a minute to run.

Suggest more fine grain durations like:

  • just a moment ago
  • about 5 seconds ago
  • about 10 seconds
  • 15, 25, 30, 40 50
  • about 1 minute ago

Auto language

I was looking for a way to make the language of the text the same as the language of the phone. But I didn't find it.
There is a possibility that it can be adapted to the telephone language (Spanish / English)

Make API more customizable

I have a proposal on how to make the package more customizable, including having different rules per locale: It's basically a declarative way of formulating the business logic currently hardcoded in the package.

Proposed architecture

I propose an architecture of formatters, matchers, and rules.

Formatters just take a locale, a DateTime to format and another DateTime relative to which to format the first one and turn it into a String and a Duration after which the string becomes invalid:

// TimeAgoInput contains a Locale, a DateTime value and a DateTime relativeTo.
// FormattingResult contains a String and a Duration.
typedef Formatter = FormattingResult Function(TimeAgoInput);

A Formatters class could contain some predefined formatters, while developers are welcome to create their own. Here are some examples of formatters:

  • Some that always return a constant value, for example, "just now", "a moment ago", or "yesterday".
  • Some that return the date difference in minutes, hours, weeks, months, years as in "21 minutes ago", "1 week ago", "3 months ago", "2 years ago".
  • Some that return the weekday: "Monday", "Thursday".

Matchers take a locale, date and current date and return whether it matches and a duration after which the matching status will change:

// MatchingResult contains a bool and a Duration.
typedef Matcher = MatchingResult Function(TimeAgoInput);

Matchers could have some common matcher types:

  • difference(from, to), checking if the Duration between both dates is between from and to (if from < difference < to).
  • Checking if the date is today or yesterday or the dayBeforeYesterday.

Finally, rules combine matchers and formatters. Users could then customize the formatting by providing a list of rules.

final matchers = [
  Rule(matcher: Matchers.difference(to: 20.seconds), formatter: Formatters.justNow), // just now
  Rule(matcher: Matchers.difference(to: 40.seconds), formatter: Formatters.aMomentAgo), // a moment ago
  Rule(matcher: Matchers.difference(to: 45.minutes), formatter: Formatters.minutesAgo), // 12 minutes ago
  Rule(matcher: Matchers.difference(to: 90.minutes), formatter: Formatters.aboutAnHour), // about an hour ago
  Rule(matcher: Matchers.today, formatter: Formatters.hoursAgo), // 4 hours ago
  Rule(matcher: Matchers.yesterday, formatter: Formatters.yesterday), // yesterday
  Rule(matcher: Matchers.withinLastWeek, formatter: Formatters.weekday), // Monday
  …
]
timeago.format(rules, …);

This would give users of this package much more flexibility. Additionally, because formatters could return the localized String as well as the Duration after which it gets invalid, it could make the Flutter part of the package much more efficient.

Showcases of the new architecture

Several issues could get resolved:

  • #47: Use a rule like Rule(matcher: Matcher.difference(to: 1.days), formatter: Formatters.exact).
  • #80: Create a formatter that respects the Locale.
  • #89: Just use fewer rules than the default.
  • #100: Just use different formatters that don't use "ago" and "from now".

Additional goodies include being able to customize the matching by Locale. In Germany, for example, there's "vorgestern", a word which describes the day before yesterday. One could easily imagine including a Matcher.dayBeforeYesterday which only matches in the German locale.

There are even cases where providing a whole set of new formatters makes sense. For example, to create Telegram-style ambiguous-by-design "last seen recently" formats.
Or in our Schul-Cloud app, where teachers will be able to see when students submitted their work for an assignment, formats like "just in time" or "5 minutes before the deadline" would become possible:

final rules = [
  Rule(
    matcher: Matcher.difference(to: 1.minutes),
    formatter: (input) => 'justInTime',
  ),
  Rule(
    matcher: Matcher.difference(to: 1.hours),
    formatter: (input) => '${input.difference.minutes} minutes before the deadline',
  ),
  …
];

Evaluation

I know this is a stark divergence from the current architecture of the package and will result in a new breaking version. But localization and time formatting are both areas where a lot of variation is going on. Most developers want to have more control over the rules than just tweaking a few settings in a pre-defined function. This approach is modular by design and that's why I believe implementing this change could make the package drastically more powerful and adaptable to developers' needs.

What still needs to be resolved

Locales won't be able to be specified in a single file. Rather than having locales in one file and the different formats inside the locale, I believe it would have to go the other way around: There are a number of formatters and in each formatter, all the applicable translations are contained.

What do you think about this proposed change? I'm looking forward to hearing your opinion.
I'd be happy to help implement the changes.

Invalid date format: eg: 2020-1-6 15:3:8

Hi admin,

I try string 2020-1-6 15:3:8 convert error: timeago.format(DateTime.parse(2020-1-6 15: 3: 8)) => Error
If I use: timeago.format(DateTime.parse(2020-01-06 15: 03:08)), that's fine
Please help me fix it.

Flutter auto update timeAgo.

Hello, this is not an issue, its more of how to, using flutter how do i have the feeling of time ago auto increment by time?
right now i dot as follow;

                    var time = timeago.format(date,allowFromNow: true,clock:timeStamp );

Thank you.

Timeago Widget doesn't automatically refresh?

Problem: The Timeago widget doesn't automatically refresh.

To Reproduce
Use the widget like this:

Timeago(
  builder: (_, value) => Text(value),
  date: DateTime.now(),
)

Expectation
It displays "a moment ago" initially, but after a minute, it displays something like "1 minute ago"

Actual
It always displays "a moment ago" no matter how much time has passed.

Screen Shot 2020-10-10 at 7 26 17 AM

Support more languages

The following languages are missing localization:

  • hindi hi
  • swedish sv
  • finnish fi

There are probably many more localizations missing.

We could perhaps make a script using the Google Cloud Translation API, to translate for all languages.

Can't change language

it's not issue.. but help)

String _parseDate(String date){

    timeago.setLocaleMessages('ru', timeago.RuMessages());
    final parsedDate = DateTime.parse(date);

    return timeago.format(parsedDate);
  }

but it returns english messages

Duplicated days for locale ar

Duplicated days for Arabic locale
7 days ago --> "منذ 77 ايام"
Although it is supposed to be "منذ 7 ايام"

DateTime objects instead of int (milliseconds)

Instead of taking milliseconds (as an integer), could the default method take a DateTime instead? With perhaps alternative ways to use it with a Duration and/or milliseconds?

It seems the most useful way of using this function is with DateTime objects:

// Desired way of using the package: not possible yet

var startTime = new DateTime.now();

while (...) {
   // do something
   print(TimeAgo.timeAgo(startTime));
}

Calling millisecondsSinceEpoch on the DateTime object is just extra common code that it is forcing most applications to write.

// Current way of using the package

var startTime = new DateTime.now();

while (...) {
   // do something
   print(TimeAgo.timeAgo(startTime.millisecondsSinceEpoch()));
}

timeago_flutter published?

Hi,

May I know is timeago_flutter published?
I am using the latest verson 2.0.29 but doesn't seems to find the timeago_flutter.

Thanks.

Add option to specify range in which apply fuzzy timestpamp

Add option to specify range in which apply fuzzy timestpamp, if its out of range it should show a date instead. e.g. something like

TimeAgo time = new TimeAgo({range: '1day', datefmt:'dd/MM/yyyy'});
int current = new DateTime.now().millisecondsSinceEpoch;

print(time.timeAgo(current - (2 * 24* 60 * 60 * 1000))); // Should print a date like '01/12/2015'

Fix german translations

Please fix german translations as follows:

vor x Tage must be vor x Tagen

There is a missing n at the end of plural strings.

Version solving failed.

Need support for intl ^0.16.0, I get the following error:

Because timeago ^1.3.0 depends on intl ^0.15.1 and my_app depends on intl ^0.16.0, timeago ^1.3.0 is forbidden.

My current workaround is using intl ^0.15.1.

Will there be an update to the package?

Shorthand format

It would nice to have a shorthand format like
"3min ago" or "3M ago" or "3m ago" or "3s ago" or "3y ago"

I think moment provides that.

export LookupMessages type

Current Behavior:

In order to implement LookupMessage and call setLocaleMessages for custom locales or custom locales, we must currently import an implementation file, which the analyzer complains about.

Solution

export LookupMessage as part of the top-level timeago library.

Workaround

// ignore_for_file: implementation_imports

import 'package:timeago/timeago.dart' as timeago;
import 'package:timeago/src/messages/lookupmessages.dart';

class MyCustomLookupMessages implements LookupMessages {
  // ...
}

// ...

timeago.setLocaleMessages("custom", MyCustomLookupMessages());

Locale changing couldn't work in flutter

I have run your example code in flutter:

 final fifteenAgo = new DateTime.now().subtract(new Duration(minutes: 15));
  final fifteenFromNow = new DateTime.now().add(new Duration(minutes: 15));

  print(ta.format(fifteenAgo)); // 15 minutes ago
  print(ta.format(fifteenFromNow, until: true)); // 15 minutes from now
  // Change locale
  ta.locale = 'es';
  print(ta.format(fifteenAgo)); // hace 15 minutos
  print(ta.format(fifteenFromNow, until: true));

but the result is :

I/flutter ( 5283): 15 minutes ago
I/flutter ( 5283): 15 minutes from now
I/flutter ( 5283): 15 minutes ago
I/flutter ( 5283): 15 minutes from now

ta.locale = 'es' doesn't work.

timeago version is 1.2.7

There would be a need for support for conjugation of time units.

First of all, I apologize for my poor English, but I have even little knowledge of the language so I called the Google Translator for help.

There are languages where translation could be solved without conjugation, but in ordinary language is used this.

For example, in Hungarian:

a minute ago      -> egy perce      // perc -e
a minute from now -> egy perc múlva // perc

an hour ago       -> egy órája      // órá -ja (different suffix)
an hour from now  -> egy óra múlva  // óra     (no accent)

There is currently no way to do this, as the suffix also depends on the unit of time, over and above that the root of the word may changes when it is conjugated.

I was could to use a "hack", which assumes that suffixAgo or suffixFromNow is called sooner than the methods for time units.
So if the order changes later, it can ruin my solution.

It would also be sufficient if the time unit methods also would get the value of _allowFromNow.

Thank you in advance for your help

date conversion error

I am receiving this answer from my API -> 1994-02-22 00: 00: 00.000 , but when using the plugin for conversion, I have the answer "26 years", 1 year longer than the correct one ... I only get the correct conversion when timestamp months are higher than month 06.

Use with Flutter Intl localization

Thanks for this great package.

How can make it work with Flutter's Intl package?

I am trying to give the manual toggle in the app for language change, and want the locale with this package to auto update.
Please help!

Code of my localization dart files:

app_localization.dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:praja/l10n/messages_all.dart';

class AppLocalization {
  static String localeName = "en";

  static Future<AppLocalization> load(Locale locale) {
    final String name =
        locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
    localeName = Intl.canonicalizedLocale(name);
    return initializeMessages(localeName).then((_) {
      Intl.defaultLocale = localeName;
      return AppLocalization();
    });
  }

  static AppLocalization of(BuildContext context) {
    return Localizations.of<AppLocalization>(context, AppLocalization);
  }

  // list of locales
  String get heyWorld {
    return Intl.message(
      'Hey World',
      name: 'heyWorld',
      desc: 'Simple word for greeting ',
    );
  }
}

app_localization_delegate.dart

import 'package:flutter/material.dart';
import 'package:praja/locale/app_localization.dart';

class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalization> {
  final Locale overriddenLocale;

  const AppLocalizationDelegate(this.overriddenLocale);

  @override
  bool isSupported(Locale locale) => ['en', 'te'].contains(locale.languageCode);

  @override
  Future<AppLocalization> load(Locale locale) => AppLocalization.load(locale);

  @override
  bool shouldReload(LocalizationsDelegate<AppLocalization> old) => false;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.