I need to get day of year (day1 is 1rst of january), week of year, and month of year from a dart DateTime object.
I did not find any available library for this. Any idea ?
[ORIGINAL ANSWER - Please scroll below to the updated answer, which has an updated calculation]
Week of year:
/// Calculates week number from a date as per https://en.wikipedia.org/wiki/ISO_week_date#Calculation
int weekNumber(DateTime date) {
int dayOfYear = int.parse(DateFormat("D").format(date));
return ((dayOfYear - date.weekday + 10) / 7).floor();
}
The rest is available through DateFormat (part of the intl package).
[UPDATED ANSWER] As pointed out by Henrik Kirk in a comment, the original answer did not include the necessary correction for certain dates. Here is a full implementation of the ISO week date calculation.
/// Calculates number of weeks for a given year as per https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year
int numOfWeeks(int year) {
DateTime dec28 = DateTime(year, 12, 28);
int dayOfDec28 = int.parse(DateFormat("D").format(dec28));
return ((dayOfDec28 - dec28.weekday + 10) / 7).floor();
}
/// Calculates week number from a date as per https://en.wikipedia.org/wiki/ISO_week_date#Calculation
int weekNumber(DateTime date) {
int dayOfYear = int.parse(DateFormat("D").format(date));
int woy = ((dayOfYear - date.weekday + 10) / 7).floor();
if (woy < 1) {
woy = numOfWeeks(date.year - 1);
} else if (woy > numOfWeeks(date.year)) {
woy = 1;
}
return woy;
}
Day of year
final date = someDate;
final diff = now.difference(new DateTime(date.year, 1, 1, 0, 0));
final diffInDays = diff.inDays;
Week of year
final date = someDate;
final startOfYear = new DateTime(date.year, 1, 1, 0, 0);
final firstMonday = startOfYear.weekday;
final daysInFirstWeek = 8 - firstMonday;
final diff = date.difference(startOfYear);
var weeks = ((diff.inDays - daysInFirstWeek) / 7).ceil();
// It might differ how you want to treat the first week
if(daysInFirstWeek > 3) {
weeks += 1;
}
Month of year
final monthOfYear = new DateTime.now().month;
Caution: That's not battle-tested code.
Try this really simple dart package, Jiffy. The code below will help
To get date day of year
// This will return the day of year from now
Jiffy.now().dayOfYear; // 295
// You can also pass in a dateTime object
Jiffy.parseFromDateTime(DateTime(2019, 1, 3)).dayOfYear; // 3
To get week of year
Jiffy.now().week; // 43
// You can also pass in an Array or Map
Jiffy.parseFromList([2019, 1, 3]).week; // 1
To get month of year
Jiffy.now().month; // 10
Jiffy.parseFromMap({
"year": 2019,
"month": 1,
"day": 3
}).month; // 1
Hope this answer helps
This is my implementation of ISO 8601 Week of Year in Dart:
int getWeekOfYear(DateTime date) {
final weekYearStartDate = getWeekYearStartDateForDate(date);
final dayDiff = date.difference(weekYearStartDate).inDays;
return ((dayDiff + 1) / 7).ceil();
}
DateTime getWeekYearStartDateForDate(DateTime date) {
int weekYear = getWeekYear(date);
return getWeekYearStartDate(weekYear);
}
int getWeekYear(DateTime date) {
assert(date.isUtc);
final weekYearStartDate = getWeekYearStartDate(date.year);
// in previous week year?
if(weekYearStartDate.isAfter(date)) {
return date.year - 1;
}
// in next week year?
final nextWeekYearStartDate = getWeekYearStartDate(date.year + 1);
if(isBeforeOrEqual(nextWeekYearStartDate, date)) {
return date.year + 1;
}
return date.year;
}
DateTime getWeekYearStartDate(int year) {
final firstDayOfYear = DateTime.utc(year, 1, 1);
final dayOfWeek = firstDayOfYear.weekday;
if(dayOfWeek <= DateTime.thursday) {
return addDays(firstDayOfYear, 1 - dayOfWeek);
}
else {
return addDays(firstDayOfYear, 8 - dayOfWeek);
}
}
Note that the "week year" is not always the calendar year, it could also be the one before or after:
void printWeekOfYear(DateTime date) {
print('week ${getWeekOfYear(date)} in year ${getWeekYear(date)}');
}
printWeekOfYear(DateTime.utc(2017, 1, 1));
// --> week 52 in year 2016
printWeekOfYear(DateTime.utc(2019, 12, 31));
// --> week 1 in year 2020
int isoWeekNumber(DateTime date) {
int daysToAdd = DateTime.thursday - date.weekday;
DateTime thursdayDate = daysToAdd > 0 ? date.add(Duration(days: daysToAdd)) : date.subtract(Duration(days: daysToAdd.abs()));
int dayOfYearThursday = dayOfYear(thursdayDate);
return 1 + ((dayOfYearThursday - 1) / 7).floor();
}
int dayOfYear(DateTime date) {
return date.difference(DateTime(date.year, 1, 1)).inDays;
}
Dart SDK2.8.4 and later:
day of the year , with no packages:
void main(){
final now = new DateTime.now();
final todayInDays = now.difference(new DateTime(now.year,1,1,0,0)).inDays; //return 157
}
reference (official)> inDays, from Dart Official documentation
I wrote another solution based on your answers, it seem to work fine, but please feel free to give me feedback if you see a problem:
class DateUtils {
static int currentWeek() {
return weekOfYear(DateTime.now());
}
static int weekOfYear(DateTime date) {
DateTime monday = weekStart(date);
DateTime first = weekYearStartDate(monday.year);
int week = 1 + (monday.difference(first).inDays / 7).floor();
if (week == 53 && DateTime(monday.year, 12, 31).weekday < 4)
week = 1;
return week;
}
static DateTime weekStart(DateTime date) {
// This is ugly, but to avoid problems with daylight saving
DateTime monday = DateTime.utc(date.year, date.month, date.day);
monday = monday.subtract(Duration(days: monday.weekday - 1));
return monday;
}
static DateTime weekEnd(DateTime date) {
// This is ugly, but to avoid problems with daylight saving
// Set the last microsecond to really be the end of the week
DateTime sunday = DateTime.utc(date.year, date.month, date.day, 23, 59, 59, 999, 999999);
sunday = sunday.add(Duration(days: 7 - sunday.weekday));
return sunday;
}
static DateTime weekYearStartDate(int year) {
final firstDayOfYear = DateTime.utc(year, 1, 1);
final dayOfWeek = firstDayOfYear.weekday;
return firstDayOfYear.add(Duration(days: (dayOfWeek <= DateTime.thursday ? 1 : 8) - dayOfWeek));
}
}
getWeekOfYear(){
DateTime _kita=DateTime.now();
int d=DateTime.parse("${_kita.year}-01-01").millisecondsSinceEpoch;
int t= _kita.millisecondsSinceEpoch;
double daydiff= (t- d)/(1000 * (3600 * 24));
double week= daydiff/7;
return(week.ceil());
}
Tested and working you do not need any package
This calculation works for me.
int dayOfWeek({DateTime date}) {
if (date == null)
date = DateTime.now();
int w = ((dayOfYear(date) - date.weekday + 10) / 7).floor();
if (w == 0) {
w = getYearsWeekCount(date.year-1);
} else if (w == 53) {
DateTime lastDay = DateTime(date.year, DateTime.december, 31);
if (lastDay.weekday < DateTime.thursday) {
w = 1;
}
}
return w;
}
int getYearsWeekCount(int year) {
DateTime lastDay = DateTime(year, DateTime.december, 31);
int count = dayOfWeek(date: lastDay);
if (count == 1)
count = dayOfWeek(date: lastDay.subtract(Duration(days: 7)));
return count;
}
int dayOfYear(DateTime date) {
int total = 0;
for (int i = 1; i < date.month; i++) {
total += getDayOfMonth(date.year, i);
}
total+=date.day;
return total;
}
int getDayOfMonth(int year, int month) {
final List<int> days = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (year % 4 == 0) days[DateTime.february]++;
return days[month];
}
the previous most voted solution is not working, if the year changes. for example has December 2020 a 53. week and if i change to January 2021 the previous solution computed 0 and not 53.
so i wrote a DateTime extension to cover year change.
int get weekNumber {
if (weekday > DateTime.thursday) {
int toSubstract = weekday - DateTime.thursday;
DateTime thursday = subtract(Duration(days: toSubstract));
if (thursday.year != year) {
return thursday.weekNumber;
}
}
int dayOfYear = int.parse(format('D'));
return ((dayOfYear - weekday + 10) / 7).floor();
}
The correct answer of @András Szepesházi but as DateTime extension
extension DateTimeExt on DateTime {
/// Calculates week number from a date as per https://en.wikipedia.org/wiki/ISO_week_date#Calculation
int get weekNumber {
int dayOfYear = int.parse(DateFormat("D").format(this));
int woy = ((dayOfYear - weekday + 10) / 7).floor();
if (woy < 1) {
woy = _numOfWeeks(year - 1);
} else if (woy > _numOfWeeks(year)) {
woy = 1;
}
return woy;
}
/// Calculates number of weeks for a given year as per https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year
int _numOfWeeks(int year) {
DateTime dec28 = DateTime(year, 12, 28);
int dayOfDec28 = int.parse(DateFormat("D").format(dec28));
return ((dayOfDec28 - dec28.weekday + 10) / 7).floor();
}
}
static int getWeekNumber(DateTime datetime) {
var day1 = DateTime(datetime.year);
DateTime firstMonday;
switch (day1.weekday) {
case 1: // mon
firstMonday = day1;
break;
case 2: // tue
firstMonday = day1.add(const Duration(days: 6));
break;
case 3: // wed
firstMonday = day1.add(const Duration(days: 5));
break;
case 4: // thir
firstMonday = day1.add(const Duration(days: 4));
break;
case 5: // fri
firstMonday = day1.add(const Duration(days: 3));
break;
case 6: // sat
firstMonday = day1.add(const Duration(days: 2));
break;
case 7: // sun
firstMonday = day1.add(const Duration(days: 1));
break;
default:
firstMonday = day1;
}
Duration sinceStartOfYear = datetime.diff(firstMonday);
double weekNo = (sinceStartOfYear.inDays / 7);
var no = weekNo.floor();
return no + 1;
}
My full tested method.