Come faccio a trovare l'inizio della settimana (sia domenica che lunedì) conoscendo l'ora corrente in C #?
Qualcosa di simile a:
DateTime.Now.StartWeek(Monday);
Come faccio a trovare l'inizio della settimana (sia domenica che lunedì) conoscendo l'ora corrente in C #?
Qualcosa di simile a:
DateTime.Now.StartWeek(Monday);
Risposte:
Utilizzare un metodo di estensione. Sono la risposta a tutto, lo sai! ;)
public static class DateTimeExtensions
{
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
int diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7;
return dt.AddDays(-1 * diff).Date;
}
}
Quale può essere usato come segue:
DateTime dt = DateTime.Now.StartOfWeek(DayOfWeek.Monday);
DateTime dt = DateTime.Now.StartOfWeek(DayOfWeek.Sunday);
dt
è UTC ed è già l'inizio della settimana, ad es. 2012-09-02 16:00:00Z
Che è Mon, 03 Sep 2012 00:00:00
in ora locale. Quindi deve convertirsi dt
in ora locale o fare qualcosa di un po 'più intelligente. Dovrebbe inoltre restituire il risultato come UTC se l'input fosse UTC.
DateTime.Parse("2012-09-02 16:00:00Z")
restituisce l'equivalente dell'ora locale e questo metodo restituisce correttamente la stessa ora, come l'ora locale. Se si utilizza DateTime.Parse("2012-09-02 16:00:00Z").ToUniversalTime()
per passare esplicitamente l'ora UTC, questo metodo restituisce correttamente 6 giorni, 16 ore prima, come ora UTC. Funziona esattamente come mi aspettavo.
dt
. Ho usatoint diff = dt.Date.DayOfWeek - startOfWeek;
Il modo più veloce che posso trovare è:
var sunday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
Se desideri che un altro giorno della settimana sia la tua data di inizio, tutto ciò che devi fare è aggiungere il valore DayOfWeek alla fine
var monday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek + (int)DayOfWeek.Monday);
var tuesday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek + (int)DayOfWeek.Tuesday);
Un po 'più prolisso e attento alla cultura:
System.Globalization.CultureInfo ci =
System.Threading.Thread.CurrentThread.CurrentCulture;
DayOfWeek fdow = ci.DateTimeFormat.FirstDayOfWeek;
DayOfWeek today = DateTime.Now.DayOfWeek;
DateTime sow = DateTime.Now.AddDays(-(today - fdow)).Date;
CultureInfo.CurrentCulture
invece di toglierla dal thread in quel modo. Sembra un modo strano di accedervi.
Now
proprietà due volte. Se l'ora corrente passa tra le due chiamate 24:00 (o 12:00 mezzanotte), la data sarà cambiata.
Utilizzando DateTime fluente :
var monday = DateTime.Now.Previous(DayOfWeek.Monday);
var sunday = DateTime.Now.Previous(DayOfWeek.Sunday);
public static DateTime Previous(this DateTime start, DayOfWeek day) { do { start = start.PreviousDay(); } while (start.DayOfWeek != day); return start; }
Brutto ma almeno restituisce le date giuste
Con l'inizio della settimana impostato dal sistema:
public static DateTime FirstDateInWeek(this DateTime dt)
{
while (dt.DayOfWeek != System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
dt = dt.AddDays(-1);
return dt;
}
Senza:
public static DateTime FirstDateInWeek(this DateTime dt, DayOfWeek weekStartDay)
{
while (dt.DayOfWeek != weekStartDay)
dt = dt.AddDays(-1);
return dt;
}
Uniamo la risposta sicura per la cultura e la risposta del metodo di estensione:
public static class DateTimeExtensions
{
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
System.Globalization.CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
DayOfWeek fdow = ci.DateTimeFormat.FirstDayOfWeek;
return DateTime.Today.AddDays(-(DateTime.Today.DayOfWeek- fdow));
}
}
dt
invece di DateTime.Today
, per avvolgere la matematica in un (offset + 7) % 7
modo per garantire un offset negativo, per usare un sovraccarico del metodo a parametro singolo che passa FirstDayOfWeek
l' startOfWeek
argomento della cultura corrente come argomento, e possibilmente (a seconda delle specifiche) per forzare un zero offset a un offset di 7 giorni, in modo che "martedì scorso" non ritorni oggi se è già martedì.
Questo potrebbe essere un po 'un trucco, ma puoi lanciare la proprietà .DayOfWeek su un int (è un enum e dal momento che non ha cambiato il suo tipo di dati sottostante è impostato come predefinito) e usarlo per determinare l'inizio della settimana precedente .
Sembra che la settimana specificata nell'enum DayOfWeek abbia inizio domenica, quindi se sottraggiamo 1 da questo valore sarà uguale a quanti giorni è il lunedì prima della data corrente. Dobbiamo anche mappare la domenica (0) in modo che sia uguale a 7, quindi dato 1 - 7 = -6 la domenica verrà mappata al lunedì precedente: -
DateTime now = DateTime.Now;
int dayOfWeek = (int)now.DayOfWeek;
dayOfWeek = dayOfWeek == 0 ? 7 : dayOfWeek;
DateTime startOfWeek = now.AddDays(1 - (int)now.DayOfWeek);
Il codice per la domenica precedente è più semplice in quanto non è necessario apportare questa modifica: -
DateTime now = DateTime.Now;
int dayOfWeek = (int)now.DayOfWeek;
DateTime startOfWeek = now.AddDays(-(int)now.DayOfWeek);
Per lunedì
DateTime startAtMonday = DateTime.Now.AddDays(DayOfWeek.Monday - DateTime.Now.DayOfWeek);
Per domenica
DateTime startAtSunday = DateTime.Now.AddDays(DayOfWeek.Sunday- DateTime.Now.DayOfWeek);
using System;
using System.Globalization;
namespace MySpace
{
public static class DateTimeExtention
{
// ToDo: Need to provide culturaly neutral versions.
public static DateTime GetStartOfWeek(this DateTime dt)
{
DateTime ndt = dt.Subtract(TimeSpan.FromDays((int)dt.DayOfWeek));
return new DateTime(ndt.Year, ndt.Month, ndt.Day, 0, 0, 0, 0);
}
public static DateTime GetEndOfWeek(this DateTime dt)
{
DateTime ndt = dt.GetStartOfWeek().AddDays(6);
return new DateTime(ndt.Year, ndt.Month, ndt.Day, 23, 59, 59, 999);
}
public static DateTime GetStartOfWeek(this DateTime dt, int year, int week)
{
DateTime dayInWeek = new DateTime(year, 1, 1).AddDays((week - 1) * 7);
return dayInWeek.GetStartOfWeek();
}
public static DateTime GetEndOfWeek(this DateTime dt, int year, int week)
{
DateTime dayInWeek = new DateTime(year, 1, 1).AddDays((week - 1) * 7);
return dayInWeek.GetEndOfWeek();
}
}
}
Mettendo tutto insieme, con la globalizzazione e consentendo di specificare il primo giorno della settimana come parte della chiamata che abbiamo
public static DateTime StartOfWeek ( this DateTime dt, DayOfWeek? firstDayOfWeek )
{
DayOfWeek fdow;
if ( firstDayOfWeek.HasValue )
{
fdow = firstDayOfWeek.Value;
}
else
{
System.Globalization.CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
fdow = ci.DateTimeFormat.FirstDayOfWeek;
}
int diff = dt.DayOfWeek - fdow;
if ( diff < 0 )
{
diff += 7;
}
return dt.AddDays( -1 * diff ).Date;
}
var now = System.DateTime.Now;
var result = now.AddDays(-((now.DayOfWeek - System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek + 7) % 7)).Date;
Questo ti darebbe mezzanotte la prima domenica della settimana:
DateTime t = DateTime.Now;
t -= new TimeSpan ((int) t.DayOfWeek, t.Hour, t.Minute, t.Second);
Questo ti dà il primo lunedì a mezzanotte:
DateTime t = DateTime.Now;
t -= new TimeSpan ((int) t.DayOfWeek - 1, t.Hour, t.Minute, t.Second);
prova con questo in c # .Con questo codice puoi ottenere sia il primo che l'ultimo giorno di una determinata settimana. Qui la domenica è il primo giorno e il sabato è l'ultimo giorno ma puoi impostare entrambi i giorni in base alla tua cultura
DateTime firstDate = GetFirstDateOfWeek(DateTime.Parse("05/09/2012").Date,DayOfWeek.Sunday);
DateTime lastDate = GetLastDateOfWeek(DateTime.Parse("05/09/2012").Date, DayOfWeek.Saturday);
public static DateTime GetFirstDateOfWeek(DateTime dayInWeek, DayOfWeek firstDay)
{
DateTime firstDayInWeek = dayInWeek.Date;
while (firstDayInWeek.DayOfWeek != firstDay)
firstDayInWeek = firstDayInWeek.AddDays(-1);
return firstDayInWeek;
}
public static DateTime GetLastDateOfWeek(DateTime dayInWeek, DayOfWeek firstDay)
{
DateTime lastDayInWeek = dayInWeek.Date;
while (lastDayInWeek.DayOfWeek != firstDay)
lastDayInWeek = lastDayInWeek.AddDays(1);
return lastDayInWeek;
}
Ho provato diversi ma non ho risolto il problema con una settimana a partire da un lunedì, risultando nel darmi il prossimo lunedì di domenica. Quindi l'ho modificato un po 'e l'ho fatto funzionare con questo codice:
int delta = DayOfWeek.Monday - DateTime.Now.DayOfWeek;
DateTime monday = DateTime.Now.AddDays(delta == 1 ? -6 : delta);
return monday;
dt.AddDays(DayOfWeek.Monday - dt.DayOfWeek);
Passaggio 1: creare una classe statica
public static class TIMEE
{
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
int diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7;
return dt.AddDays(-1 * diff).Date;
}
public static DateTime EndOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
int diff = (7 - (dt.DayOfWeek - startOfWeek)) % 7;
return dt.AddDays(1 * diff).Date;
}
}
Passaggio 2: utilizzare questa classe per ottenere sia il giorno di inizio che di fine della settimana
DateTime dt =TIMEE.StartOfWeek(DateTime.Now ,DayOfWeek.Monday);
DateTime dt1 = TIMEE.EndOfWeek(DateTime.Now, DayOfWeek.Sunday);
(6 - (dt.DayOfWeek - startOfWeek)) % 7
per me contro i test unitari che ho scritto.
Il seguente metodo dovrebbe restituire il DateTime desiderato. Passa vero per domenica essendo il primo giorno della settimana, falso per lunedì:
private DateTime getStartOfWeek(bool useSunday)
{
DateTime now = DateTime.Now;
int dayOfWeek = (int)now.DayOfWeek;
if(!useSunday)
dayOfWeek--;
if(dayOfWeek < 0)
{// day of week is Sunday and we want to use Monday as the start of the week
// Sunday is now the seventh day of the week
dayOfWeek = 6;
}
return now.AddDays(-1 * (double)dayOfWeek);
}
Grazie per gli esempi Avevo bisogno di usare sempre "CurrentCulture" il primo giorno della settimana e per un array avevo bisogno di conoscere l'esatto Daynumber .. quindi ecco le mie prime estensioni:
public static class DateTimeExtensions
{
//http://stackoverflow.com/questions/38039/how-can-i-get-the-datetime-for-the-start-of-the-week
//http://stackoverflow.com/questions/1788508/calculate-date-with-monday-as-dayofweek1
public static DateTime StartOfWeek(this DateTime dt)
{
//difference in days
int diff = (int)dt.DayOfWeek - (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek; //sunday=always0, monday=always1, etc.
//As a result we need to have day 0,1,2,3,4,5,6
if (diff < 0)
{
diff += 7;
}
return dt.AddDays(-1 * diff).Date;
}
public static int DayNoOfWeek(this DateTime dt)
{
//difference in days
int diff = (int)dt.DayOfWeek - (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek; //sunday=always0, monday=always1, etc.
//As a result we need to have day 0,1,2,3,4,5,6
if (diff < 0)
{
diff += 7;
}
return diff + 1; //Make it 1..7
}
}
Nessuno sembra aver ancora risposto correttamente. Incollerò la mia soluzione qui nel caso qualcuno ne abbia bisogno. Il seguente codice funziona indipendentemente dal fatto che il primo giorno della settimana sia un lunedì o una domenica o qualcos'altro.
public static class DateTimeExtension
{
public static DateTime GetFirstDayOfThisWeek(this DateTime d)
{
CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
var first = (int)ci.DateTimeFormat.FirstDayOfWeek;
var current = (int)d.DayOfWeek;
var result = first <= current ?
d.AddDays(-1 * (current - first)) :
d.AddDays(first - current - 7);
return result;
}
}
class Program
{
static void Main()
{
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
Console.WriteLine("Current culture set to en-US");
RunTests();
Console.WriteLine();
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("da-DK");
Console.WriteLine("Current culture set to da-DK");
RunTests();
Console.ReadLine();
}
static void RunTests()
{
Console.WriteLine("Today {1}: {0}", DateTime.Today.Date.GetFirstDayOfThisWeek(), DateTime.Today.Date.ToString("yyyy-MM-dd"));
Console.WriteLine("Saturday 2013-03-02: {0}", new DateTime(2013, 3, 2).GetFirstDayOfThisWeek());
Console.WriteLine("Sunday 2013-03-03: {0}", new DateTime(2013, 3, 3).GetFirstDayOfThisWeek());
Console.WriteLine("Monday 2013-03-04: {0}", new DateTime(2013, 3, 4).GetFirstDayOfThisWeek());
}
}
Modulo in C # funziona male per -1mod7 (dovrebbe essere 6, c # restituisce -1) quindi ... la soluzione "oneliner" a questo apparirà così :)
private static DateTime GetFirstDayOfWeek(DateTime date)
{
return date.AddDays(-(((int)date.DayOfWeek - 1) - (int)Math.Floor((double)((int)date.DayOfWeek - 1) / 7) * 7));
}
Lo stesso per la fine della settimana (nello stile di @Compile Questa è la risposta):
public static DateTime EndOfWeek(this DateTime dt)
{
int diff = 7 - (int)dt.DayOfWeek;
diff = diff == 7 ? 0 : diff;
DateTime eow = dt.AddDays(diff).Date;
return new DateTime(eow.Year, eow.Month, eow.Day, 23, 59, 59, 999) { };
}
Potresti usare l'eccellente libreria Umbrella :
using nVentive.Umbrella.Extensions.Calendar;
DateTime beginning = DateTime.Now.BeginningOfWeek();
Tuttavia, essi non sembrano aver memorizzato Lunedi come il primo giorno della settimana (vedere la proprietà nVentive.Umbrella.Extensions.Calendar.DefaultDateTimeCalendarExtensions.WeekBeginsOn
), in modo che la soluzione localizzata precedente è un po 'meglio. Sfortunato.
Modifica : guardando più da vicino alla domanda, sembra che anche Umbrella potrebbe funzionare anche per quello:
// Or DateTime.Now.PreviousDay(DayOfWeek.Monday)
DateTime monday = DateTime.Now.PreviousMonday();
DateTime sunday = DateTime.Now.PreviousSunday();
Anche se vale la pena notare che se chiedi il lunedì precedente di lunedì, ti restituirà sette giorni indietro. Ma questo vale anche se lo usi BeginningOfWeek
, che sembra un bug :(.
Ciò restituirà le date di inizio della settimana e di fine della settimana:
private string[] GetWeekRange(DateTime dateToCheck)
{
string[] result = new string[2];
TimeSpan duration = new TimeSpan(0, 0, 0, 0); //One day
DateTime dateRangeBegin = dateToCheck;
DateTime dateRangeEnd = DateTime.Today.Add(duration);
dateRangeBegin = dateToCheck.AddDays(-(int)dateToCheck.DayOfWeek);
dateRangeEnd = dateToCheck.AddDays(6 - (int)dateToCheck.DayOfWeek);
result[0] = dateRangeBegin.Date.ToString();
result[1] = dateRangeEnd.Date.ToString();
return result;
}
Ho pubblicato il codice completo per il calcolo dell'inizio / fine della settimana, mese, trimestre e anno sul mio blog ZamirsBlog
namespace DateTimeExample
{
using System;
public static class DateTimeExtension
{
public static DateTime GetMonday(this DateTime time)
{
if (time.DayOfWeek != DayOfWeek.Monday)
return GetMonday(time.AddDays(-1)); //Recursive call
return time;
}
}
internal class Program
{
private static void Main()
{
Console.WriteLine(DateTime.Now.GetMonday());
Console.ReadLine();
}
}
}
Ecco una combinazione di alcune delle risposte. Utilizza un metodo di estensione che consente di passare la cultura, se non viene passata, viene utilizzata la cultura corrente. Ciò garantirà la massima flessibilità e riutilizzo.
/// <summary>
/// Gets the date of the first day of the week for the date.
/// </summary>
/// <param name="date">The date to be used</param>
/// <param name="cultureInfo">If none is provided, the current culture is used</param>
/// <returns>The date of the beggining of the week based on the culture specifed</returns>
public static DateTime StartOfWeek(this DateTime date, CultureInfo cultureInfo=null) =>
date.AddDays(-1 * (7 + (date.DayOfWeek - (cultureInfo??CultureInfo.CurrentCulture).DateTimeFormat.FirstDayOfWeek)) % 7).Date;
Esempio di utilizzo:
public static void TestFirstDayOfWeekExtension() {
DateTime date = DateTime.Now;
foreach(System.Globalization.CultureInfo culture in CultureInfo.GetCultures(CultureTypes.UserCustomCulture | CultureTypes.SpecificCultures)) {
Console.WriteLine($"{culture.EnglishName}: {date.ToShortDateString()} First Day of week: {date.StartOfWeek(culture).ToShortDateString()}");
}
}
se vuoi sabato o domenica o qualsiasi giorno della settimana ma non superare la settimana corrente (sabato-domenica), ti copro con questo codice.
public static DateTime GetDateInCurrentWeek(this DateTime date, DayOfWeek day)
{
var temp = date;
var limit = (int)date.DayOfWeek;
var returnDate = DateTime.MinValue;
if (date.DayOfWeek == day) return date;
for (int i = limit; i < 6; i++)
{
temp = temp.AddDays(1);
if (day == temp.DayOfWeek)
{
returnDate = temp;
break;
}
}
if (returnDate == DateTime.MinValue)
{
for (int i = limit; i > -1; i++)
{
date = date.AddDays(-1);
if (day == date.DayOfWeek)
{
returnDate = date;
break;
}
}
}
return returnDate;
}
Ci piace il one-liner: ottieni la differenza tra il primo giorno della settimana della cultura corrente e il giorno corrente, quindi sottrai il numero di giorni dal giorno corrente
var weekStartDate = DateTime.Now.AddDays(-((int)now.DayOfWeek - (int)DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek));
A seguito di Compilare questa 'risposta, utilizzare il seguente metodo per ottenere la data per qualsiasi giorno della settimana:
public static DateTime GetDayOfWeek(this DateTime dt, DayOfWeek day)
{
int diff = (7 + (dt.DayOfWeek - DayOfWeek.Monday)) % 7;
var monday = dt.AddDays(-1 * diff).Date;
switch (day)
{
case DayOfWeek.Tuesday:
return monday.AddDays(1).Date;
case DayOfWeek.Wednesday:
return monday.AddDays(2).Date;
case DayOfWeek.Thursday:
return monday.AddDays(3).Date;
case DayOfWeek.Friday:
return monday.AddDays(4).Date;
case DayOfWeek.Saturday:
return monday.AddDays(5).Date;
case DayOfWeek.Sunday:
return monday.AddDays(6).Date;
}
return monday;
}
Prova a creare una funzione che utilizza la ricorsione. L'oggetto DateTime è un input e la funzione restituisce un nuovo oggetto DateTime che rappresenta l'inizio della settimana.
DateTime WeekBeginning(DateTime input)
{
do
{
if (input.DayOfWeek.ToString() == "Monday")
return input;
else
return WeekBeginning(input.AddDays(-1));
} while (input.DayOfWeek.ToString() == "Monday");
}
Il calcolo in questo modo ti consente di scegliere quale giorno della settimana indica l'inizio di una nuova settimana (nell'esempio che ho scelto lunedì).
Notare che questo calcolo per un giorno che è un lunedì darà il lunedì corrente e non quello precedente.
//Replace with whatever input date you want
DateTime inputDate = DateTime.Now;
//For this example, weeks start on Monday
int startOfWeek = (int)DayOfWeek.Monday;
//Calculate the number of days it has been since the start of the week
int daysSinceStartOfWeek = ((int)inputDate.DayOfWeek + 7 - startOfWeek) % 7;
DateTime previousStartOfWeek = inputDate.AddDays(-daysSinceStartOfWeek);
int diff = dayOfWeek - dt.DayOfWeek; return dt.AddDays(diff).Date;