Parse arbitrary length date String with DateTimeFormatter - date

I am attempting to parse a date string of (almost) arbitrary length. The approach I had with SimpleDateFormat was something like this
private Date parseWithSimpleDateFormat(String dateString) throws ParseException {
String pattern = "yyyyMMddHHmmss".substring(0, dateString.length());
SimpleDateFormat format = new SimpleDateFormat(pattern);
return format.parse(dateString);
}
... which I want to do "better" with the new Date API. What I've come up with is the following
private static final DateTimeFormatter FLEXIBLE_FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("yyyy[MM[dd[HH[mm[ss]]]]]")
.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.toFormatter();
private Date parseWithDateTimeFormatter(String dateString) {
LocalDateTime localDateTime = LocalDateTime.parse(dateString, FLEXIBLE_FORMATTER);
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
Instant instant = zonedDateTime.toInstant();
return Date.from(instant);
}
with the following outcome
parseWithDateTimeFormatter("2016"); // works as intended
parseWithDateTimeFormatter("201605"); // Text '201605' could not be parsed at index 0
parseWithDateTimeFormatter("20160504"); // Text '20160504' could not be parsed at index 0
parseWithDateTimeFormatter("2016050416"); // Text '2016050416' could not be parsed at index 0
parseWithDateTimeFormatter("201605041636"); // Text '201605041636' could not be parsed at index 0
What am I doing wrong here, or how would I further troubleshoot this?

You can use this modified formatter in order to avoid parsing more than 4 digits for the year:
private static final DateTimeFormatter FLEXIBLE_FORMATTER =
new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendPattern("[MM[dd[HH[mm[ss]]]]]")
.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.toFormatter();
In contrast to other fields like month (MM) etc., the year field symbol y has no limitation to four digits as indicated by count of y-letters.

Related

how to subtract two different times in flutter

I want to subtract two different times in flutter for example
String time1 = "07:00";
String time2 = "08:12";
String time3 = time2 - time1;
//result will be 01:12
this is just a sample data explanation of what I want to achieve.
See the sample code below. It prints 01:12 in the end.
Input Data:
String time1 = "07:00";
String time2 = "08:12";
Required Methods to be defined:
DateTime getTime(final String inputString) => DateFormat("hh:mm").parse(inputString);
String getString(final Duration duration) {
String formatDigits(int n) => n.toString().padLeft(2, '0');
final String minutes = formatDigits(duration.inMinutes.remainder(60));
return "${formatDigits(duration.inHours)}:$minutes";
}
Computation
final String difference = getString(getTime(time2).difference(getTime(time1)));
Printing the result
print(difference); // 01:12
Have fun - but keep in mind to change the naming of the methods to better fit into your context.
You should use Dart's built-in DateTime class and its DateTime.parse especially.
Documentation: https://api.dart.dev/stable/2.8.4/dart-core/DateTime/parse.html
Try out below code for get difference between two times.
var timeFormat = DateFormat("HH:mm"); //Time format
var first = timeFormat.parse("10:40");
var second = timeFormat.parse("18:20");
print("Difference -->${second.difference(first)}");
// prints Difference -->7:40
Flutter|Dart provides a data type to handle dates : DateTime. So instead of using String, use DateTime :
DateTime time1 = DateTime.parse(your_date_here your_time);
DateTime time2 = DateTime.parse(your_date_here your_time);
DateTime time3 = time2.difference(time1);
If you want just the time part, you can format it using DateFormat from the intl package. You'll need to import it as follows :
import 'package:intl/intl.dart';
Then do the following:
String formattedTime = DateFormat.Hms().format(time1);
String formattedTime = DateFormat.Hms().format(time2);
Or you can just directly format the result (time3):
String formattedTime = DateFormat.Hms().format(time3);

Neatly parsing a date in "MMddyy" format along with other formats in dart

I guess it is not possible to parse a date in "MMddyy" format in dart.
void main() {
String strcandidate = "031623";
String format = "MMddyy";
var originalFormat = DateFormat(format).parse(strcandidate);
}
Output:
Uncaught Error: FormatException: Trying to read dd from 031623 at position 6
The following works fine when parsing a date in "MM-dd-yy" format.
void main() {
String strcandidate = "03-16-23";
String format = "MM-dd-yy";
var originalFormat = DateFormat(format).parse(strcandidate);
}
In the problem, the input date string can be in any format e.g ['yyyy-MM-dd', 'MMM'-yyyy, 'MM/dd/yy']. I am parsing the input string for these formats in a loop as follows.
dateFormatsList = ['yyyy-MM-dd', 'MMM'-yyyy, 'MM/dd/yy'];
for (String format in dateFormatsList ) {
try {
originalFormat = DateFormat(format).parse(strcandidate);
dateFound = true;
} catch (e) {}
}
Adding 'MMddyy' to dateFormatsList is not going to work.
But regular expression be used to parse this format.
However if all formats are parsed using parse method and one additional format is parsed using regular expression, then the code is not that neat, and cluttered.
To write as much neat and efficient code as possible, if you want, you can share your insights about any possibility for making it efficient and clean while incorporating 'MMddyy'format. Tysm!
See How do I convert a date/time string to a DateTime object in Dart? for how to parse various date/time strings to DateTime objects.
If you need to mix approaches, you can provide a unified interface. Instead of using a List<String> for your list of formats, you can use a List<DateTime Function(String)>:
import 'package:intl/intl.dart';
/// Parses a [DateTime] from [dateTimeString] using a [RegExp].
///
/// [re] must have named groups with names `year`, `month`, and `day`.
DateTime parseDateFromRegExp(RegExp re, String dateTimeString) {
var match = re.firstMatch(dateTimeString);
if (match == null) {
throw FormatException('Failed to parse: $dateTimeString');
}
var year = match.namedGroup('year');
var month = match.namedGroup('month');
var day = match.namedGroup('day');
if (year == null || month == null || day == null) {
throw ArgumentError('Regular expression is malformed');
}
// In case we're parsing a two-digit year format, instead of
// parsing the strings ourselves, reparse it with [DateFormat] so that it can
// apply its -80/+20 rule.
//
// [DateFormat.parse] doesn't work without separators, which is why we
// can't use directly on the original string. See:
// https://github.com/dart-lang/intl/issues/210
return DateFormat('yy-MM-dd').parse('$year-$month-$day');
}
typedef DateParser = DateTime Function(String);
DateParser dateParserFromRegExp(String rePattern) =>
(string) => parseDateFromRegExp(RegExp(rePattern), string);
var parserList = [
DateFormat('yyyy-MM-dd').parse,
DateFormat('MMM-yyyy').parse,
DateFormat('MM/dd/yy').parse,
dateParserFromRegExp(
r'^(?<month>\d{2})(?<day>\d{2})(?<year>\d{4})$',
)
];
void main() {
var strcandidate = '12311776';
DateTime? originalFormat;
for (var tryParse in parserList) {
try {
originalFormat = tryParse(strcandidate);
break;
} on Exception {
// Try the next format.
}
}
print(originalFormat);
}
I think it's a bit hacky but what about use a regular expression (RegExp) to parse the date divider and then replace it with just ""?
void main() {
String strcandidate = "031623";
String strYear = strcandidate.substring(4);
//Taken 20 as the year like 2023 as year is in 2 digits
String _newDateTime = '20' + strYear + strcandidate.substring(0, 4);
var _originalFormat = DateTime.parse(_newDateTime);
print(_originalFormat);
}
add the intl to yaml then write this code:
import 'package:intl/intl.dart';
void main() {
var strcandidate = DateTime(2023, 3, 16);
String format = "MMddyy";
var originalFormat = DateFormat(format).format(strcandidate);
print(originalFormat);
}

Flutter/Dart Set Hour and Minutes in Current Date [duplicate]

I have an instance of DateTime and I would like to format that to a String. How do I do that? I want to turn the date into a string, something like "2013-04-20".
You can use the intl package (installer) to format dates.
For en_US formats, it's quite simple:
import 'package:intl/intl.dart';
main() {
final DateTime now = DateTime.now();
final DateFormat formatter = DateFormat('yyyy-MM-dd');
final String formatted = formatter.format(now);
print(formatted); // something like 2013-04-20
}
There are many options for formatting. From the docs:
ICU Name Skeleton
-------- --------
DAY d
ABBR_WEEKDAY E
WEEKDAY EEEE
ABBR_STANDALONE_MONTH LLL
STANDALONE_MONTH LLLL
NUM_MONTH M
NUM_MONTH_DAY Md
NUM_MONTH_WEEKDAY_DAY MEd
ABBR_MONTH MMM
ABBR_MONTH_DAY MMMd
ABBR_MONTH_WEEKDAY_DAY MMMEd
MONTH MMMM
MONTH_DAY MMMMd
MONTH_WEEKDAY_DAY MMMMEEEEd
ABBR_QUARTER QQQ
QUARTER QQQQ
YEAR y
YEAR_NUM_MONTH yM
YEAR_NUM_MONTH_DAY yMd
YEAR_NUM_MONTH_WEEKDAY_DAY yMEd
YEAR_ABBR_MONTH yMMM
YEAR_ABBR_MONTH_DAY yMMMd
YEAR_ABBR_MONTH_WEEKDAY_DAY yMMMEd
YEAR_MONTH yMMMM
YEAR_MONTH_DAY yMMMMd
YEAR_MONTH_WEEKDAY_DAY yMMMMEEEEd
YEAR_ABBR_QUARTER yQQQ
YEAR_QUARTER yQQQQ
HOUR24 H
HOUR24_MINUTE Hm
HOUR24_MINUTE_SECOND Hms
HOUR j
HOUR_MINUTE jm
HOUR_MINUTE_SECOND jms
HOUR_MINUTE_GENERIC_TZ jmv
HOUR_MINUTE_TZ jmz
HOUR_GENERIC_TZ jv
HOUR_TZ jz
MINUTE m
MINUTE_SECOND ms
SECOND s
For non-en_US dates, you need to explicitly load in the locale. See the DateFormat docs for more info. The date_symbol_data_local.dart contains all of the formats for each country/language, if you would like a more in-depth look.
This will work too:
DateTime today = new DateTime.now();
String dateSlug ="${today.year.toString()}-${today.month.toString().padLeft(2,'0')}-${today.day.toString().padLeft(2,'0')}";
print(dateSlug);
pubspec.yaml:
dependencies:
intl:
main.dart:
import 'package:intl/intl.dart'; // for date format
import 'package:intl/date_symbol_data_local.dart'; // for other locales
void main() {
var now = DateTime.now();
print(DateFormat().format(now)); // This will return date using the default locale
print(DateFormat('yyyy-MM-dd hh:mm:ss').format(now));
print(DateFormat.yMMMMd().format(now)); // print long date
print(DateFormat.yMd().format(now)); // print short date
print(DateFormat.jms().format(now)); // print time
initializeDateFormatting('es'); // This will initialize Spanish locale
print(DateFormat.yMMMMd('es').format(now)); // print long date in Spanish format
print(DateFormat.yMd('es').format(now)); // print short date in Spanish format
print(DateFormat.jms('es').format(now)); // print time in Spanish format
}
Result:
May 31, 2020 5:41:42 PM
2020-05-31 05:41:42
May 31, 2020
5/31/2020
5:41:42 PM
31 de mayo de 2020
31/5/2020
17:41:42
You can also specify the date format like stated earlier: https://pub.dev/documentation/intl/latest/intl/DateFormat-class.html
import 'package:intl/intl.dart';
String formatDate(DateTime date) => new DateFormat("MMMM d").format(date);
Produces: March 4
If someone wants to convert a date in string format to some other string format first use DateTime.parse("2019-09-30") then pass it to DateFormat("date pattern").format() like
dateFormate = DateFormat("dd-MM-yyyy").format(DateTime.parse("2019-09-30"));
Reference: Dart - How to change format of simple date string which is in yyyy-MM-dd to dd-MM-yyyy
You can use this method as well, if you don't want to add another library
DateTime dateTime = DateTime.now();
String YYYY_MM_DD = dateTime.toIso8601String().split('T').first;
print(YYYY_MM_DD); //2020-11-23
This give you the date like in a social network : ["today","yesterday","dayoftheweek",etc..]
void main() {
DateTime now = new DateTime(2018,6,26);
print(date(now));
}
String date(DateTime tm) {
DateTime today = new DateTime.now();
Duration oneDay = new Duration(days: 1);
Duration twoDay = new Duration(days: 2);
Duration oneWeek = new Duration(days: 7);
String month;
switch (tm.month) {
case 1:
month = "january";
break;
case 2:
month = "february";
break;
case 3:
month = "march";
break;
case 4:
month = "april";
break;
case 5:
month = "may";
break;
case 6:
month = "june";
break;
case 7:
month = "july";
break;
case 8:
month = "august";
break;
case 9:
month = "september";
break;
case 10:
month = "october";
break;
case 11:
month = "november";
break;
case 12:
month = "december";
break;
}
Duration difference = today.difference(tm);
if (difference.compareTo(oneDay) < 1) {
return "today";
} else if (difference.compareTo(twoDay) < 1) {
return "yesterday";
} else if (difference.compareTo(oneWeek) < 1) {
switch (tm.weekday) {
case 1:
return "monday";
case 2:
return "tuesday";
case 3:
return "wednesday";
case 4:
return "thursday";
case 5:
return "friday";
case 6:
return "saturday";
case 7:
return "sunday";
}
} else if (tm.year == today.year) {
return '${tm.day} $month';
} else {
return '${tm.day} $month ${tm.year}';
}
}
You can use the intl package to format dates in flutter.
void main() {
final DateTime now = DateTime.now();
final DateFormat format = DateFormat('yyyy-MM-dd');
final String formatted = format.format(now);
// 2021-03-02
}
or you can use date_format package to format dates in flutter.
import 'package:date_format/date_format.dart';
final formattedStr = formatDate(DateTime.now(), [dd, '-', mm, '-', yyyy]);
//02-03-2021
Another way, using intl package.
Create an extension of DateTime:
date_time_extension.dart
import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart';
extension DateTimeExtension on DateTime {
String format([String pattern = 'dd/MM/yyyy', String? locale]) {
if (locale != null && locale.isNotEmpty) {
initializeDateFormatting(locale);
}
return DateFormat(pattern, locale).format(this);
}
}
Import this file where you are going to use DateTime type, and you can use it like this:
DateTime.now().format();
DateTime.now().format('MM/yyyy');
DateTime.now().format('MM/yyyy', 'es');
There is a package date_format
dependencies:
date_format:
code
import 'package:date_format/date_format.dart';
final formattedStr = formatDate(
yourDateTime, [dd, '.', mm, '.', yy, ' ', HH, ':', nn]);
// output example "29.03.19 07:00"
Pay attention: minutes are nn
link to the package
main() {
final String pattern = 'yyyy-MM-dd';
final String formatted = DateFormat(pattern).format(DateTime.now());
print(formatted);
}
Changing yyyy-MM-dd string you can change your date format. I made app for play with this pattern string.
You can experiment format string in my app It made with flutter.
https://biplobsd.github.io/EpochConverterApp
Here you can see how can I edit the pattern and this effect showing on top
/// Get date as a string for display.
String getFormattedDate(String date) {
/// Convert into local date format.
var localDate = DateTime.parse(date).toLocal();
/// inputFormat - format getting from api or other func.
/// e.g If 2021-05-27 9:34:12.781341 then format must be yyyy-MM-dd HH:mm
/// If 27/05/2021 9:34:12.781341 then format must be dd/MM/yyyy HH:mm
var inputFormat = DateFormat('yyyy-MM-dd HH:mm');
var inputDate = inputFormat.parse(localDate.toString());
/// outputFormat - convert into format you want to show.
var outputFormat = DateFormat('dd/MM/yyyy HH:mm');
var outputDate = outputFormat.format(inputDate);
return outputDate.toString();
}
Set your project intl pakage
dateTimeFormet (date){
//MM-dd-yyyy
//yyyy-MM-dd
return DateFormat('dd-MM-yyyy').format(date);// you can set your formet
}
void main (){
var date = 01-11-2022 00 : 00
var _datetime = dateTimeFormet(date);
print(_dateTime);
}
In the case you want to combine several date format into one, this is how we can do using intl.
DateFormat('yMMMd').addPattern(DateFormat.HOUR24_MINUTE).format(yourDateTime))
NO DEPENDENCY METHOD [FOR DISPLAYING DATE AS FORMATTED STRING]
If you want to show your DateTime value as a day/month/year or any other format you like, string interpolation can be handy :
"${_date.day} / ${_date.month} / ${_date.year}"
sample output :
23 / 4 / 1920
I don't want to use any additional library, so i went this way.
handling yearly quarters, from string to DateTime, I didn't find proper solution so made this:
List<String> dateAsList = 'Q1 2001'.split(' ');
DateTime dateTime = DateTime.now();
String quarter = dateAsList[0];
int year = int.parse(dateAsList[1]);
switch(quarter) {
case "Q1": dateTime = DateTime(year, 1);
break;
case "Q2": dateTime = DateTime(year, 4);
break;
case "Q3": dateTime = DateTime(year, 7);
break;
case "Q4": dateTime = DateTime(year, 10);
break;
}
To get a nice user-friendly string that includes both the date and the time, you can use this:
import 'package:intl/intl.dart';
main() {
final DateTime someDateTime = DateTime(2017, 9, 7, 17, 30);
final DateFormat formatter = DateFormat.yMMMd().add_jms();
final String formatted = formatter.format(someDateTime);
print(formatted); // Sep 7, 2017 5:30:00 PM (in the US)
}
import 'package:intl/intl.dart';
main() {
var formattedDate = new DateTime.Format('yyyy-MM-dd').DateTime.now();
print(formattedDate); // something like 2020-04-16
}
For more details can refer DateFormat Documentation
String formatDate(String date) {
return date.substring(0, 10).split('-').reversed.join().replaceAll('-', '/');
}
From format "yyyy-mm-dd H:i:s"
String dateConverter(String date) {
// Input date Format
final format = DateFormat("dd-MM-yyyy");
DateTime gettingDate = format.parse(date);
final DateFormat formatter = DateFormat('yyyy-MM-dd');
// Output Date Format
final String formatted = formatter.format(gettingDate);
return date;
}
A simpler way:
new DateFormat("dd-MM-y").format(YOUR_DATETIME_HERE)
Use "H:mm" to see full minutes like 13:08 not 13:8
Since the flutter usual Datetime library doesn't know the locale for Germany - neither de, nor DE, nor de_DE, nor de-DE or any other combinations, for example if you want to have the name of the month or the name of the day written in human readable string, I suggest you to use the following code.
install pub flutter pub add date_format
String formattedDate = formatDate(DateTime(year, month, day),[dd,'. ', MM, ' ', yyyy], locale: GermanDateLocale());
Current Day:
DateTime.now().day, //something like 26
Current Month:
DateTime.now().month, //something like 4
Current Year:
DateTime.now().year, //something like 2022
Current Houre:
DateTime.now().hour, //something like 12
Current Minute:
DateTime.now().minute, //something like 13
Current Second:
DateTime.now().second, //something like 44

How to compare LocalDate instances Java 8

I am writing an app that needs to be quite accurate in dates and I wonder how can I compare LocalDate instances.. for now I was using something like:
LocalDate localdate1 = LocalDate().now();
LocalDate localdate2 = someService.getSomeDate();
localdate1.equals(localdate2);
But I noticed that my app is giving me some confusing results, and I think it is because of the date comparing.
I am thinking about obtaining the time from 1970' in long and compare those two, but I must be easier, I am sure of it
Using equals()
LocalDate does override equals:
int compareTo0(LocalDate otherDate) {
int cmp = (year - otherDate.year);
if (cmp == 0) {
cmp = (month - otherDate.month);
if (cmp == 0) {
cmp = (day - otherDate.day);
}
}
return cmp;
}
If you are not happy with the result of equals(), you are good using the predefined methods of LocalDate.
isAfter()
isBefore()
isEqual()
Notice that all of those method are using the compareTo0() method and just check the cmp value. if you are still getting weird result (which you shouldn't), please attach an example of input and output
LocalDate ld ....;
LocalDateTime ldtime ...;
ld.isEqual(LocalDate.from(ldtime));
I believe this snippet will also be helpful in a situation where the dates comparison spans more than two entries.
static final int COMPARE_EARLIEST = 0;
static final int COMPARE_MOST_RECENT = 1;
public LocalDate getTargetDate(List<LocalDate> datesList, int comparatorType) {
LocalDate refDate = null;
switch(comparatorType)
{
case COMPARE_EARLIEST:
//returns the most earliest of the date entries
refDate = (LocalDate) datesList.stream().min(Comparator.comparing(item ->
item.toDateTimeAtCurrentTime())).get();
break;
case COMPARE_MOST_RECENT:
//returns the most recent of the date entries
refDate = (LocalDate) datesList.stream().max(Comparator.comparing(item ->
item.toDateTimeAtCurrentTime())).get();
break;
}
return refDate;
}

convert string to datetime and compare for the 2 date diff

Question 1: I have 2 fields to let user enter start date and end date, but in string format
- DateStart (string: yyyy/mm/dd hh:mm)
- DateEnd (string: yyyy/mm/dd hh:mm)
May I how to compare both datetime? I want to know total how many hours is difference between the both date.
Question 2: user will enter 1 returnDate (string: yyyy/mm/dd hh:mm) also in string format, may I know how to update the returnDate if I will need to add 55hours on the returnDate?
Thanks
Start by taking a look at SimpleDateFormat, which will allow you to convert the String value to a Date object.
For example...
try {
// Note hh is Hour in am/pm (1-12), based on you example, it's not possible
// now the day part (ie am or pm), you could supply aa as the am/pm marker
// or use HH which is Hour in day (0-23)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm");
Date date = sdf.parse("2014/04/11 4:46");
System.out.println(date);
} catch (ParseException exp) {
exp.printStackTrace();
}
Then you can use JodaTime to calculate the difference between the two dates, see How to find difference between two Joda-Time DateTimes in minutes for an example
It should be noted that you could skip the use of SimpleDateFormat and JodaTime all the way, check out String to joda LocalDate in format of "dd-MMM-yy" for an example of converting a String to a LocalDate using JodaTime
To add time to an existing Date, you can use either Calendar or JodaTime, see how to add days to java simple date format for an example of both
I would recommend that if you are using some kind of GUI, you might consider using one of the available date pickers as it will save you a lot of hassel
I suggest using Java8's java.util.time package
Example:
public static void main(String[] args) {
// example input
String dateString1 = "2014/04/10 00:00";
String dateString2 = "2014/04/11 23:59";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
LocalDateTime date1 = LocalDateTime.parse(dateString1, dtf);
LocalDateTime date2 = LocalDateTime.parse(dateString2, dtf);
// do your stuff with the dates...
}
Here is my solution:
String date1 = "2014/04/10 15:30";
String date2 = "2014/04/11 09:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm");
try {
Date parsedDate1 = sdf.parse(date1);
Date parsedDate2 = sdf.parse(date2);
double secs = (parsedDate2.getTime() - parsedDate1.getTime()) / 1000;
double hours = secs / 3600;
System.out.println(hours);
} catch (ParseException e) {
e.printStackTrace();
}
For adding hours to a date:
Date date = new Date(someDateObject.getTime() + 55 * 3600 * 1000);