Runtime: Adicionar GetISOWeekOfYear()

Criado em 9 abr. 2018  ·  139Comentários  ·  Fonte: dotnet/runtime

Justificativa

.Net não implementa o padrão ISO 8601 - tem esquema alternativo em:
``` c#
System.Globalization.Calendar.GetWeekOfYear(DateTime time, regra CalendarWeekRule, DayOfWeek firstDayOfWeek);

Unix `date` utility implements ISO 8601:

data +%V

In [PowerShell repo ](https://github.com/PowerShell/PowerShell/pull/6542) we use workaround described [here](https://blogs.msdn.microsoft.com/shawnste/2006/01/24/iso-8601-week-of-year-format-in-microsoft-net/) (see Keno's comment) for:
```powershell
Get-Date -UFormat %V

.Net deve ter paridade e implementação nativa.

A ISO 8601 é independente de cultura para que possamos usar métodos estáticos.

Se estamos indo na direção, acredito que faça sentido considerar todos os objetos ISO8601 e compatibilidade com o utilitário Unix date .
https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar

  • primeira semana
  • Semana Anterior
  • semanas por ano

http://man7.org/linux/man-pages/man1/date.1.html

  • %g últimos dois dígitos do ano do número da semana ISO (veja %G)
  • %G ano do número da semana ISO (veja %V); normalmente útil apenas com %V
  • %V Número da semana ISO, com segunda-feira como primeiro dia da semana (01..53)

API proposta

c# namespace System.Globalization { public abstract class Calendar : ICloneable { public static class ISOWeek { public static int GetWeekOfYear(DateTime time); public static int GetYear(DateTime time); public static DateTime GetYearStart(int year); public static DateTime GetYearEnd(int year); public static int GetWeeksInYear(int year); public static DateTime ToDateTime(int year, int week, DayOfWeek day); } }

Observe que a API proposta é um membro estático e não de instância. A razão é que a semana ISO é independente da cultura e do calendário.

Hackathon api-approved area-System.Globalization up-for-grabs

Comentários muito úteis

Feito! Eu acompanho o repo há anos de qualquer maneira 😉

Todos 139 comentários

Por que não adicionar um novo membro para ISO a CalendarWeekRule ?

@svick E então ignore firstDayOfWeek (a menos que seja segunda-feira)? A ISO 8601 especifica segunda-feira como o primeiro dia da semana.

É basicamente o GetWeekOfYear existente com CalendarWeekRule.FirstFourDayWeek + DayOfWeek.Monday e um pouquinho de mudança de comportamento. Consulte https://blogs.msdn.microsoft.com/shawnste/2006/01/24/iso-8601-week-of-year-format-in-microsoft-net/

@khellang

Provavelmente, uma escolha melhor seria exigir que firstDayOfWeek fosse segunda-feira (e jogar de outra forma).

Mas nesse ponto, a proposta original de adicionar um novo método pode ser melhor.

Eu acredito que é melhor adicionar um novo membro ao CalendarWeekRule enum. Algo como Iso8601 ou Iso8601ModayFirstDayOfWeek. Eu não acho que precisamos adicionar uma nova API para isso. se você concorda, poderia atualizar a proposta?

CC @shawnsteele

A outra ideia poderia ser adicionar o novo membro Iso8601 ao enum CalendarWeekRule

E então, ter uma sobrecarga no método

System.Globalization.Calendar.GetWeekOfYear(DateTime time, regra CalendarWeekRule);

que assumem que segunda-feira é o primeiro dia da semana.

E Faça System.Globalization.Calendar.GetWeekOfYear(DateTime time, regra CalendarWeekRule, DayOfWeek firstDayOfWeek); jogar se firstDayOfWeek não for segunda-feira e a regra for Iso8601.

podemos listar todas as propostas alternativas e discuti-las com o comitê de design.

Suponha que o terceiro parâmetro deva ser segunda-feira e, caso contrário, lance uma exceção - este caso não parece conveniente. Não vejo vantagem nessa exceção.
Podemos ignorar o terceiro parâmetro silenciosamente se o segundo parâmetro for Iso8601 .
Ou podemos tornar o terceiro parâmetro opcional com o padrão de segunda-feira.

@iSazonov é por isso que sugeri a outra ideia de ter a sobrecarga

C# System.Globalization.Calendar.GetWeekOfYear(DateTime time, CalendarWeekRule rule);

que assumem segunda-feira como o primeiro dia da semana.

Eu listaria todas as opções alternativas de design na descrição desta questão e então podemos escolher a melhor delas ao discuti-la com o comitê de design.

Vou atualizar a proposta com suas ideias.

@tarekgh API proposta atualizada. Sinta-se à vontade para corrigir se eu pulei alguma coisa.

Obrigado, @iSazonov modifiquei um pouco mas não alterei nada na proposta.

Adicionar um Iso8601Week à enumeração é uma ideia razoável.
Uma observação peculiar que observei é que alguns aplicativos desejam saber a semana ISO, mas perguntam a localidades/culturas qual é sua preferência de contagem de semanas. Que tipo de funciona para algumas localidades que foram mapeadas para as regras da semana ISO, mas depois quebra para outras localidades.

@ShawnSteele, qual exatamente sua sugestão aqui em relação à sua nota peculiar? Acho que o Windows pode precisar começar a sinalizar as localidades que precisam de semanas ISO e a estrutura mapearia essas localidades para usar o novo valor de enumeração que apresentamos.

@tarekgh Duas coisas:
1) Os aplicativos que desejam explicitamente as regras da semana ISO porque é assim que o aplicativo funciona provavelmente precisam de GetISOWeekOfYear(). Parece bobo para mim um aplicativo que "precisa" do comportamento ISO para obter um calendário para uma cultura/idioma e tentar corrigi-lo. Eles querem um comportamento explícito, deve ser razoavelmente fácil.
2) Algumas culturas pretendem ter um comportamento de semana ISO. A estrutura provavelmente deve selecionar o comportamento da regra da semana ISO quando vir o Windows LOCALE_IFIRSTWEEKOFYEAR de "2" (primeiros quatro dias da semana).

Obrigado, @ShawnSteele

Os aplicativos que desejam explicitamente as regras da semana ISO porque é assim que o aplicativo funciona provavelmente precisam de GetISOWeekOfYear()

Então você está sugerindo que a nova API não deve fazer parte da classe de calendário. pode ser uma API estática em DateTimeFormInfo, por exemplo. direito?

Algumas culturas pretendem ter um comportamento de semana ISO. A estrutura provavelmente deve selecionar o comportamento da regra da semana ISO quando vir o Windows LOCALE_IFIRSTWEEKOFYEAR de "2" (primeiros quatro dias da semana).

Isso são detalhes de implementação, podemos falar mais sobre isso quando vamos implementá-lo. Obrigado pelo feedback.

Então você está sugerindo que a nova API não deve fazer parte da classe de calendário. pode ser uma API estática em DateTimeFormatInfo, por exemplo. direito?

Isso provavelmente seria mais apropriado, sim.

se este for o caso, devemos remover a opção de design alternativo (que sugere adicionar mais valores ao enum). e mantenha apenas uma opção que está introduzindo uma API estática. Se todos concordarem, eu vou mudar a proposta de acordo com isso.

@tarekgh - Acho que depende de quais são os principais casos de uso. Na minha experiência, muitos aplicativos desejam explicitamente a semana ISO, e o comportamento dependente da cultura é irrelevante.

É menos claro para mim se há um caso de uso razoável em que a preferência da cultura por um mecanismo de contagem de semanas ISO seja interessante para um aplicativo, mesmo que outras culturas possam usar sistemas diferentes. A maioria dos aplicativos parece querer o comportamento da semana ISO independente da cultura.

Existe algo como comportamento da semana ISO dependente da cultura? Isso não anula todo o ponto do padrão? :pensando:

Pessoalmente, gosto muito mais para onde estamos indo do que adicionar um valor enum e lançar alguma combinação de argumentos.

bom, atualizarei a proposta para ter a nova API estática (penso em tê-la na classe Calendar para descoberta) e removerei as propostas de enumeração. Acredito que ficará muito mais claro.

@khellang Esse é o meu ponto de vista. Algumas regiões também usam a semana ISO como prática cultural. Às vezes, há confusão sobre se o software deseja o padrão ISO ou a prática comum para a região.

É tolice pedir a versão da cultura da semana ISO, mas é justo perguntar se a cultura usa a semana ISO por padrão.

Se estamos indo na direção, acredito que faça sentido considerar todos os objetos ISO801 e compatibilidade com o utilitário Unix date .
https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar

  • primeira semana
  • Semana Anterior
  • semanas por ano
  • semanas por mês

http://man7.org/linux/man-pages/man1/date.1.html

  • -I data/hora de saída no formato ISO 8601
  • %g últimos dois dígitos do ano do número da semana ISO (veja %G)
  • %G ano do número da semana ISO (veja %V); normalmente útil apenas com %V
  • %V Número da semana ISO, com segunda-feira como primeiro dia da semana (01..53)

@iSazonov atualize a proposta se quiser adicionar outras funcionalidades também.

@tarekgh Feito.

por

```C#
// Não definido na ISO 8601, então pode ser removido
public static int GetISOWeeksPerMonth(DateTime time);

I prefer to remove this as it is not defined in the ISO 8601. we have the option later to add it if it is really needed. 

for 

```C#
        //-I output date/time in ISO 8601 format
        public static string GetISODatetimeFormat(DateTime time);
       // Additionally or alternatively we could implement formatting method
        public static string FormatISODatetime(DateTime time);

Não adicionamos APIs de formatação aqui. Além disso, você olhou para https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings já estamos suportando a formatação de data ISO. veja os especificadores "o" e "r". Acredito que devemos remover essas APIs da proposta. se você concordar, atualize a proposta mais uma vez e podemos prosseguir a partir daqui. obrigado.

Eu concordo.

O que exatamente

```C#
public static int GetISOYearOfISOWeek(DateTime time);

```
faz? poderia dar algum exemplo?

Desculpe, estou principalmente à espreita neste tópico, no entanto, queria salientar que as semanas ISO são contíguas na transição do ano novo de 31 de dezembro para 1º de janeiro. Portanto, a semana 1 do novo ano pode começar em dezembro do ano anterior, ou a semana 53 de maio de um ano pode incluir 1º de janeiro do ano seguinte.

Nesses casos, a "semana" pertence ao ano anterior ou ao ano seguinte, o que pode causar um comportamento estranho, como 1º de janeiro sendo parte da semana do ano anterior. O que significa que é interessante saber de qual ano aquela semana ISO seria considerada parte, por exemplo: 1 de janeiro de 2005 é 2004-W53-6 por exemplo.

Wikipedia tem um verão razoável do comportamento https://en.wikipedia.org/wiki/ISO_week_date

Observe que se você não estiver contando semanas ISO, então o ano é apenas o ano gregoriano, então uma data formatada ISO para 1º de janeiro de 2005 ainda seria 2005-01-01 - é somente quando os números das semanas estão sendo usados ​​que os anos ficar esquisito.

Portanto, "GetISOYear" não é suficiente, pois só se aplica ao contar por semana ISO. Acho que GetISOYearOfISOWeek é bastante descritivo e não consigo pensar em nada melhor.

Obrigado @shawnsteele , marquei o problema como pronto para revisão.

Pensando mais nas APIs propostas, acho melhor introduzir a classe ISOCalendar ao invés de adicionar esses métodos estáticos à classe Calendar. Quero dizer, vamos implementar o calendário ISO completo e adicionar todas as funcionalidades necessárias. o que você acha disso?

Qual é a sensação em tipos aninhados? Calendar.ISO.GetWeekOfYear ?

@tarekgh Levando em conta que o calendário ISO é independente da cultura e os métodos propostos são estáticos, sua sugestão parece muito boa e a API será facilmente descoberta.

@khellang

Qual é a sensação em tipos aninhados? Calendar.ISO.GetWeekOfYear?

Você quer dizer que ISO seria uma classe estática? Isso pode ser bom, mas ainda prefiro ter a classe IsoCalendar. o motivo é que estou vendo que o ISO é um calendário por si só (como o calendário gregoriano) e pode ser usado como qualquer outro calendário. mesmo os recursos de calendário (o padrão, livros, sites...etc.) sempre se referem a ele como um calendário.

@iSazonov

Levando em consideração que o calendário ISO é independente da cultura e os métodos propostos são estáticos, sua sugestão parece muito boa e a API será facilmente descoberta.

Concordo que é independente da cultura, mas isso não importa, pois já temos alguns calendários que não estão relacionados a culturas específicas (por exemplo, JulianCalendar). problema de descoberta não é diferente de qualquer outro calendário que suportamos hoje. Eu diria que qualquer pessoa interessada na funcionalidade ISO procuraria o calendário ISO em vez de tentar encontrar alguns métodos de classe de calendário.

FWIW, eu gosto da idéia de Calendar.ISO - semelhante à forma como há Encoding.UTF8. Presumivelmente, poderia ser um ISOCalendar.

No entanto, ainda há GetISOYearForISOWeek() que o torna uma funcionalidade extra do que outros calendários fariam.

Isso quase me faz pensar que precisa haver outro formulário ISOWeekCalendar, porque não tenho certeza do que acontece com um ISOCalendar quando você o passa para APIs de formatação. Como o sistema saberia formatá-lo como 2005-01-01 (formato de data ISO) ou 2004-W53-6 (formato de semana ISO)

Eu gosto da ideia de Calendar.ISO - Semelhante à forma como há Encoding.UTF8. Presumivelmente, poderia ser um ISOCalendar.

Com isso, precisaremos do ISOCalendar de qualquer maneira. Tendo a propriedade extra Calendar.ISO podemos ter se for realmente útil. Mas não fizemos isso com outros calendários. Ou seja, não temos Calendar.Gregorian, por exemplo. Em geral, acho que pode ser uma boa ideia, pois os usuários não precisam criar um novo objeto Agenda toda vez que quiserem usá-lo. e, em vez disso, podemos retornar a instância de calendário em cache.

No entanto, ainda há GetISOYearForISOWeek() que o torna uma funcionalidade extra do que outros calendários fariam.

Já temos os mesmos casos com os calendários Lunisolar que expõem mais métodos específicos para esses calendários.

Quase me faz pensar que precisa haver outro formulário ISOWeekCalendar porque não tenho certeza do que acontece com um ISOCalendar quando você o passa para APIs de formatação. Como o sistema saberia formatá-lo como 2005-01-01 (formato de data ISO) ou 2004-W53-6 (formato de semana ISO)

O calendário ISO seria independente da cultura e não seria usado na formatação ou análise. semelhante ao calendário juliano.

Sim, quero dizer ter uma classe estática aninhada dentro de Calendar com métodos específicos para ISO. Como já discutimos anteriormente no tópico, não faz muito sentido implementar alguns dos métodos existentes (ou pelo menos sobrecargas) da classe abstrata Calendar existente.

@khellang

Existe alguma outra API de calendário além de Calendar.GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek); que você acha que será problemática para o calendário ISO? Estou perguntando porque estou pensando em permitir que os usuários usem o ISO como qualquer outro calendário regular seria uma vantagem, em vez de ter usuários para casos especiais interagindo com o calendário ISO. Podemos definir o comportamento de Calendar.GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek); e teremos outra API Calendar.GetWeekOfYear(DateTime time);

@tarekgh Hmm, esse é um ponto interessante. "CalendarWeekRule" não tem sentido neste contexto. Qual seria o comportamento correto? Ignore isto? Fazer outra coisa?

TwoDigitYearMax não tem sentido em um calendário ISO, pois o ISO requer anos de 4 dígitos.

GetDaysInYear() para um calendário semanal ISO teria 52 ou 53 semanas de dias, certo? Isso pode ser peculiar. E seria diferente de um calendário não-ISO-Week. E não tenho certeza do que isso significa para os "meses" do calendário da semana ISO, pois esses são conceitos sem sentido em um calendário semanal da ISO. (As semanas são os meses, mais ou menos)

GetLeapMonth levanta a questão de saber se o ano da semana 52/53 em um calendário semanal ISO tem o conceito de semanas bissextas?

A ISO fornece o conceito de formatos de data em um formato de data tradicional 2018-04-16, ou no formato de semana do ano, 2018-W16-1 - o objeto Calendar pode ser usado em um DTFI.Calendar. O que significa que pode ser usado para formatação.

Normalmente, o DTFI especifica como um calendário é formatado e o Calendário fornece a matemática. No entanto, a principal coisa sobre o calendário ISO é que a ISO define explicitamente a formatação (embora a resolução do formato possa variar). As variações permitidas são em torno da resolução e da variável única do formato ISO versus formato ISO Week.

Qualquer solução provavelmente precisa não confundir a questão ISO/formatação.

TwoDigitYearMax não tem sentido em um calendário ISO, pois o ISO requer anos de 4 dígitos.

Eu acredito que isso pode se comportar como calendário gregoriano de qualquer maneira. se o ISO estiver usando ano de 4 dígitos, TwoDigitYearMax não afetará nada no cálculo do aplicativo. Não estou vendo um problema real aqui.

GetDaysInYear() para um calendário semanal ISO teria 52 ou 53 semanas de dias, certo? Isso pode ser peculiar. E seria diferente de um calendário não-ISO-Week. E não tenho certeza do que isso significa para os "meses" do calendário da semana ISO, pois esses são conceitos sem sentido em um calendário semanal da ISO. (As semanas são os meses, mais ou menos)

Veja https://en.wikipedia.org/wiki/ISO_week_date afirma"

An ISO week-numbering year (also called ISO year informally) has 52 or 53 full weeks. That is 364 or 371 days instead of the usual 365 or 366 days. The extra week is sometimes referred to as a leap week, although ISO 8601 does not use this term.

O que significa que o ano ISO é 364 ou 371 dias.

GetLeapMonth levanta a questão de saber se o ano da semana 52/53 em um calendário semanal ISO tem o conceito de semanas bissextas?

GetLeapMonth sempre retornará 0, pois não há conceito de mês bissexto no calendário ISO.
IsLeapDay e IsLeapMonth sempre retornarão false. IsLeapYear pode retornar true para os anos de 371 dias.

A ISO fornece o conceito de formatos de data em um formato de data tradicional 2018-04-16, ou no formato de semana do ano, 2018-W16-1 - o objeto Calendar pode ser usado em um DTFI.Calendar. O que significa que pode ser usado para formatação.
Normalmente, o DTFI especifica como um calendário é formatado e o Calendário fornece a matemática. No entanto, a principal coisa sobre o calendário ISO é que a ISO define explicitamente a formatação (embora a resolução do formato possa variar). As variações permitidas são em torno da resolução e da variável única do formato ISO versus formato ISO Week.
Qualquer solução provavelmente precisa não confundir a questão ISO/formatação.

O calendário ISO não será associado a nenhuma cultura (semelhante aos calendários Juliano e Lunissolar). Portanto, a formatação com este calendário não seria nenhuma preocupação.

Para Calendar.GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek); podemos forçar o comportamento a funcionar ignorando os parâmetros CalendarWeekRule e DayOfWeek. Além disso, apresentaremos a nova sobrecarga Calendar.GetWeekOfYear(DateTime time) para uso lógico. é claro, documentaremos o comportamento de ambos os métodos e podemos explicar por que eles se comportam assim.

Eu não estou realmente pressionando para ter ISOCalendar, estou apenas vendo que as pessoas estão sempre se referindo ao cálculo ISO como calendário ISO na web e nos livros (por exemplo, Calendrical Calculations). então é por isso que eu pensei que faria sentido tê-lo como um calendário por si só, em vez de ter alguns métodos estáticos como funções auxiliares.

Se você ainda vê que isso é confuso, posso explorar mais sugestões @khellang ou ficar com a última proposta.

O que significa que o ano ISO é 364 ou 371 dias.

Certo, o que eu quis dizer foi que um calendário .ISO não seria um calendário .ISOWeek. Se for usado apenas para cálculos, precisaríamos apenas de um calendário .ISOWeek (não do calendário .ISO) - mas se o calendário ISO fosse adicionado posteriormente, seria estranho.

GetLeapMonth sempre retornará 0, pois não há conceito de mês bissexto no calendário ISO.

Há um mês bissexto em um calendário ISO. Não há um mês bissexto em um calendário ISO Week. (A menos que você tenha usado os acessadores de mês? Você planeja desabilitar GetMonth() e similares?)

Estou pensando que um "calendário ISO" e "calendário semanal ISO" fazem sentido do ponto de vista da formatação - mas você pode fazer um DTFI que saiba como fazer a formatação do calendário ISO com qualquer calendário gregoriano.

Também estou pensando que adicioná-los como um calendário explícito ou dois parece sensato na superfície, mas leva a muitas perguntas estranhas e a um comportamento potencialmente inesperado. Ou pedidos adicionais.

Então, estou voltando a adicionar os dois métodos ao calendário gregoriano: GetISOWeek() e GetIsoYearOfIsoWeek() (ou GetIsoWeekYear()?) -- isso resolveria o problema imediato sem causar um monte de outros comportamentos estranhos.

Então, estou voltando a adicionar os dois métodos ao calendário gregoriano: GetISOWeek() e GetIsoYearOfIsoWeek() (ou GetIsoWeekYear()?) -- isso resolveria o problema imediato sem causar um monte de outros comportamentos estranhos.

Qual é o benefício de ter esses métodos no calendário gregoriano e não na classe abstrata Calendar? ou como @khellang sugeriu ter uma classe ISO estática na classe Calendar (ou seja, Calendar.ISO.GetISOWeek)?

Eu assumi que Calendar.ISO seria um ISOCalendar "completo". Mas se forem apenas alguns métodos, isso funcionaria, eu acho,

ISO seria uma classe estática

```C#
namespace System.Globalization
{
classe abstrata pública Calendário: ICloneable
{
classe estática pública ISO
{
public static int GetISOWeekOfYear(DateTime time);
public static int GetISOFirstWeekOfYear(DateTime time);
public static int GetISOLastWeekOfYear(DateTime time);
public static int GetISOWeeksPerYear(DateTime time);
public static int GetISOYearOfISOWeek(DateTime time);
}
}

or we can stick with the original proposal 

```C#
namespace System.Globalization
{
    public abstract class Calendar : ICloneable
    {
        // All ISO 801 objects   (https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar)
        public static int GetISOWeekOfYear(DateTime time);
        public static int GetISOFirstWeekOfYear(DateTime time);
        public static int GetISOLastWeekOfYear(DateTime time);
        public static int GetISOWeeksPerYear(DateTime time);

        // Compatibility with Unix date utility (http://man7.org/linux/man-pages/man1/date.1.html)

        // %G year of ISO week number (see %V); normally useful only with %V
        public static int GetISOYearOfISOWeek(DateTime time);
    }
}

Atualizarei a proposta para incluir a classe Calendar.ISO e listarei a proposta original como um design alternativo.

@iSazonov se estiver de acordo com isso, poderia atualizar a proposta? ou posso fazê-lo se você não tiver nenhuma objeção em alterar a proposta.

E uma vez que você tenha uma classe estática Calendar.ISO , você pode descartar todos os prefixos e sufixos ISO dos nomes dos métodos 😊

@tarekgh Sinta-se à vontade para atualizar - a proposta LGTM.

feito!

Corrigi o erro de digitação nos comentários ISO 801 -> ISO 8601

Mais uma pergunta aqui sobre:

```C#
public static int GetFirstWeekOfYear(DateTime time);
public static int GetLastWeekOfYear(DateTime time);

Will GetFirstWeekOfYear always return 1? or we are returning the relative Gregorian week number here? 
Will GetLastWeekOfYear return GetWeeksPerYear returned value? or we are returning the relative Gregorian week number here? 

wouldn't be better to have these return DateTime object which returns when the first week starts and when last week end? May we change the names too to be GetYearStart and Get YearEnd? 

```C#
            public static DateTime GetFirstWeekOfYear(DateTime time);
            public static DateTime GetLastWeekOfYear(DateTime time);

Desculpe, não tenho acompanhado :)
Estes soam mal para mim. O "calendário" tem uma configuração de semana que NÃO é a semana ISO. Portanto, se essas forem as primeiras/últimas semanas ISO, eles devem especificar o calendário da semana iso.

Não tenho ideia de como a "primeira semana iso" seria interessante, isso é sempre "1", certo? E a última semana seria como "GetLastISOWeekOfYear" - o que pode ser um pouco interessante.

O início/fim do ano iso parece interessante para mim, já que raramente é 1º de janeiro. Você também pode obter a semana # dessa data se quiser a última semana iso # do ano.

IsoWeeksPerYear muda (52/53), então "Per" parece estranho. Existem 16 onças por litro (para cada litro). IsoWeeksIn Year?

GetIsoWeeksInYear é o mesmo que a última semana ISO do ano, então eu prefiro que a primeira/última vá embora, elas são redundantes.

Eu gosto da ideia de um:
public static DateTime GetISOWeekYearStart(DateTime time);
public static DateTime GetISOWeekYearEnd(DateTime time);

Isso é exatamente o que eu queria saber sobre qual é o benefício de ter GetFirstWeekOfYear e GetLastWeekOfYear. então parece-me que estes realmente não são necessários.

por que você não gosta de retornar o DateTime apontando para o início e o final de qualquer ano? Não estou me sentindo forte com isso, mas, ao mesmo tempo, posso ver o benefício de ter essas datas. Imagine que você tenha um controle de calendário que pode marcar o início e o fim dos anos ISO. observe que podemos alterar o nome de tais APIs para algo como GetYearStart e GetYearEnd.

Você me confundiu. eu disse:

Eu gosto da ideia de um:
public static DateTime GetISOWeekYearStart(DateTime time);
public static DateTime GetISOWeekYearEnd(DateTime time);

Obviamente, eles teriam que especificar o bit "ISOWeek", pois são apenas o calendário ISO.

desculpe, eu interpretei errado como "eu não gosto".

E a nomenclatura:

C# public abstract class Calendar : ICloneable { public static class ISO { ... public static DateTime GetYearStart(DateTime time); public static DateTime GetYearEnd(DateTime time); } }

Essa nomenclatura é insuficiente.
Um calendário "ISO" é exatamente como o calendário gregoriano que todos conhecemos. Começa em 01-01-2018 e termina em 31-12-2018. Tem 365/366 anos.
Esta discussão é sobre o Calendário Semanal da ISO, que é diferente.

Portanto, a classe deve ser chamada de "ISOWeek" ou os métodos precisam especificar isso.

@ShawnSteele parece que você perdeu esses métodos já estão dentro da classe ISO.

Seria Calendar.ISO.GetYearStart/GetYearEnd. ou outra sugestão é

Calendar.ISO.GetFirstWeekStart/GetLastWeekEnd

Não, eu não perdi isso. "ISO" especifica muitas coisas diferentes sobre formatos de data. "ISO" não implica que DEVE ser o formato ISO Week Year.

A classe deve ser chamada ISOWeek ou a variação "Week" precisa ser especificada no método.

por exemplo: Calendar.ISOWeek.GetYearStart/GetYearEnd

Calendar.ISO.GetYearStart é ambíguo. Eu esperaria que fosse sempre 1º de janeiro, não o início do ano da semana ISO

por que Calendar.ISO.GetFirstWeekStart/GetLastWeekEnd não está ok?

Isso supondo que a "primeira semana" da qual você está falando seja uma semana ISO. O que parece uma suposição razoável para pessoas que entendem o sistema de calendário semanal ISO, no entanto, acho que pode ser um pouco ambíguo para os outros.

Eu não gosto do nome ISOWeek porque os outros nomes de API não fariam sentido. por exemplo, ter ISOWeek.GetWeekOfYear teria o nome "Week" redundante. Se você acha que Calendar.ISO.GetFirstWeekStart/GetLastWeekEnd pode ser ambíguo, podemos ter Calendar.ISO.GetYearStart/GetYearEnd

Os outros métodos usam "ISOWeek"? Então Calendar.ISO.GetFirstISOWeekStart?

GetYearStart/End Acho menos estranho, porém eles precisariam incluir ISOWeek. GetISOWeekYearStart/End - o que os tornaria mais desajeitados.

Os outros métodos usam "ISOWeek"? Então Calendar.ISO.GetFirstISOWeekStart?

Não. nós não. veja a proposta no topo da página e temos:

```C#
namespace System.Globalization
{
classe abstrata pública Calendário: ICloneable
{
classe estática pública ISO
{
// Todos os objetos ISO 8601 (https://en.wikipedia.org/wiki/ISO_week_date#Relation_with_the_Gregorian_calendar)
public static int GetWeekOfYear(DateTime time);
public static int GetFirstWeekOfYear(DateTime time);
public static int GetLastWeekOfYear(DateTime time);
public static int GetWeeksPerYear(DateTime time);

       // Compatibility with Unix date utility (http://man7.org/linux/man-pages/man1/date.1.html)

       // %G year of ISO week number (see %V); normally useful only with %V
        public static int GetYearOfWeek(DateTime time);
}

}
```

E quanto a ISO.GetWeekYearStart/End?

Acho "GetIsoFirstWeekStart" desajeitado. Você está realmente querendo o início/fim do ano da Semana ISO. O que acontece no início da primeira semana, mas isso é um redirecionamento mental extra desnecessário.

GetYearStart por si só é ambíguo porque não diz se é o ano do calendário ou o ano da semana.

E quanto a ISO.GetWeekYearStart/End?

Isso me parece razoável. Vou atualizar a proposta por isso, se ninguém mais se opuser :-)

Para GetWeekYearEnd, isso retornaria o início da última semana do ano? ou retornará no último dia da semana do ano?

Eu voltaria no início/fim do ano. (último dia da semana do ano para GetWeekYearEnd)

Perguntei porque pede a Semana do final do ano :-) Acho que isso pode ser entendido retornando o primeiro dia da semana que termina o ano. A confusão que estou vendo agora é, a API esclarece se estamos retornando a semana ou o dia?

Comecei a pensar que GetYearStart/End seria mais claro :-)

sobre seu comentário

GetYearStart por si só é ambíguo porque não diz se é o ano do calendário ou o ano da semana.

Isso ficará claro porque a chamada terá a palavra ISO (por exemplo, ISO.GetYearStart) que indica o início do ano ISO. Eu não estou vendo que isso é realmente ambíguo.

Eu esperaria que ISO.GetYearStart() retornasse 1 Jan e ISO.GetYearEnd() retornasse 31 Dec. Esta é a diferença entre um ano ISO e um ano de semana ISO.

Falei offline com @ShawnSteele e aqui está a proposta final com a qual concordamos, que deve remover qualquer confusão.

C# namespace System.Globalization { public abstract class Calendar : ICloneable { public static class ISOWeek { public static int GetWeekOfYear(DateTime time); public static DateTime GetYearStart(DateTime time); public static DateTime GetYearEnd(DateTime time); public static int GetWeeksPerYear(DateTime time); public static int GetYearOfWeek(DateTime time); } }

Entre em contato se alguém tiver alguma preocupação com a proposta para que eu possa atualizá-la na parte superior da página.

LGTM.

Sim, isso parece bom. Faria sentido incluir também métodos para formatar uma data de semana ISO como uma string?

Da Wikipédia:

Uma data precisa é especificada pelo ano de numeração de semana ISO no formato YYYY, um número de semana no formato ww prefixado pela letra 'W' e o número do dia da semana , um dígito d de 1 a 7, começando com segunda-feira e terminando com domingo. Por exemplo, a data gregoriana 31 de dezembro de 2006 corresponde ao domingo da 52ª semana de 2006 e é escrita 2006-W52-7 (em forma estendida) ou 2006W527 (em forma compacta).

Existe uma razão GetWeeksPerYear , GetYearStart e GetYearEnd não poderem pegar int year ?

Os métodos existentes em Calendar usam um esquema de nomenclatura diferente; GetDaysInYear , GetDaysInMonth e GetMonthsInYear . Em vez disso GetWeeksPerYear deveria ser GetWeeksInYear para consistência?

Sim, isso parece bom. Faria sentido incluir também métodos para formatar uma data de semana ISO como uma string?

Geralmente, a formatação é feita através das classes de cultura (por exemplo, DateTimeFormatInfo) mas até agora não suportamos nenhuma cultura que precise dessa formatação. podemos pensar mais tarde em fornecer semelhante ao que estamos fornecendo para formatação ISO (ou seja, formato "o") que pode suportar YYYY-Wnn-dd (ou YYYYWnndd). Eu gosto de fazer isso separadamente desta proposta.

Existe uma razão para GetWeeksPerYear, GetYearStart e GetYearEnd não poderem apenas levar o ano inteiro?

Eu pensei nisso antes, acho que os usuários usariam a Semana ISO em conjunto com o calendário gregoriano. então acredito que em cenários principais as pessoas começariam com o DateTime e é por isso que prefiro que essas APIs levem DateTime e não o número do ano. deixe-me saber se você pensa o contrário.
Além disso, você me fez pensar em outro cenário que acho que precisamos apoiar, que é obter o Gregorian DateTime da data ISO. algo como:

C# public DateTime ToDateTime(int year, int week, int day);

Eu acho que isso é importante para dar flexibilidade na conversão de ISO para gregoriano. para que as pessoas possam viajar de ida e volta para qualquer data. Se você concordar, vou adicionar este à proposta também.

Os métodos existentes no Calendar usam um esquema de nomenclatura diferente; GetDaysInYear, GetDaysInMonth e GetMonthsInYear. Em vez disso, GetWeeksPerYear deve ser GetWeeksInYear para consistência?

Essa é uma boa opinião. Atualizarei o nome da API para GetWeeksInYear. obrigado pela captura.

Não deveria ser DayOfWeek day em vez de int day ? É efetivamente "Calculando uma data com base no ano, número da semana e dia da semana" descrito na Wikipedia

Acredito que nos principais cenários as pessoas começariam com o DateTime e é por isso que prefiro que essas APIs levem DateTime e não o número do ano. deixe-me saber se você pensa o contrário.

Tentei implementar os métodos na proposta atual e os métodos mencionados acima precisam apenas de um ano gregoriano. É realmente um aborrecimento quando você precisa construir um DateTime inteiro (com mês e dia) apenas para obter a data de início ou término do ano.

Não deveria ser o dia DayOfWeek em vez do dia int?

Vou atualizar a proposta com isso. você está certo, o dia deve ser entre domingo, segunda-feira .... sábado

Tentei implementar os métodos na proposta atual e os métodos mencionados acima precisam apenas de um ano gregoriano. É realmente um incômodo quando você precisa construir um DateTime inteiro (com mês e dia) apenas para obter a data de início ou término do ano.

A questão que temo que as pessoas encontrem é o ano de entrada, é realmente o ano gregoriano? ou é ano ISO. você sabe que podemos obter algumas datas em gregoriano (por volta de 29 de dezembro) que podem pertencer ao próximo ano em ISO. ter DateTime está removendo essa confusão e o número do mês e do dia em DateTime também é muito importante para saber o mapa de datas para qual ano ISO. A outra proposta seria apenas aceitar o número do ano que é o ano ISO e não o ano gregoriano e podemos nomear o parâmetro como isoWeekYear.

minha última resposta foi apenas sobre

C# public static DateTime GetYearStart(DateTime time); public static DateTime GetYearEnd(DateTime time);

mas ainda acredito que o reset tem que levar um DateTime e não apenas um ano.

o número do mês e do dia em DateTime também é muito importante para saber o mapa de datas para qual ano ISO.

É importante em alguns dos métodos, sim, mas não nos que mencionei. A única informação necessária é um ano gregoriano. É trivial passar DateTime.Year se você já tiver uma instância DateTime , mas é totalmente desnecessário construir um DateTime (que valores eu uso para mês e dia? ? eles são usados?) apenas para passá-lo.

BTW, já existe um precedente para usar int year em Calendar.GetDaysInYear . Também podemos ser consistentes.

Posso colocar uma essência com minhas implementações rápidas para que você possa ter uma ideia das APIs e seu uso, se quiser?

É importante em alguns dos métodos, sim, mas não nos que mencionei. A única informação necessária é um ano gregoriano. É trivial passar DateTime.A year se você já tiver uma instância de DateTime, mas é totalmente desnecessário construir um DateTime (quais valores eu uso para mês e dia? isso importa? eles são usados?) apenas para passá-lo.

O que acontece se você tiver um ano gregoriano que cruze 2 anos ISO? Aqui o exemplo,

Dom, 28 de dezembro de 2008 | 2008-W52-7
Seg 29 Dez 2008 | 2009-W01-1

Portanto, se você passar 2008 para nossas APIs, será ambíguo. É por isso que mencionei que as APIs precisam levar DateTime ou precisam levar o número do ano ISO e não o número gregoriano.

BTW, já existe um precedente para usar int year em Calendar.GetDaysInYear. Também podemos ser consistentes.

Não estou me sentindo forte com isso porque essa API retornará apenas 7 * GetWeeksInYear(...)

Uma outra observação sobre o uso de DayOfWeek para o dia em vez de int na seguinte API
C# public DateTime ToDateTime(int year, int week, int day);

Semana ISO geralmente usando dias de 1 a 7, enquanto DayOfWeek tem dias de domingo=0 a sábado = 6. você acha que isso pode criar confusão? Além disso, se usarmos DayOfWeek, você acha que aceitamos valores como (DayOfWeek) 7 ?

Mais uma coisa, para as 2 APIs a seguir

C# public static class ISOWeek { public static int GetWeekOfYear(DateTime time); public static int GetYearOfWeek(DateTime time); }

devemos chamá-los de GetWeek e GetYear? Estes serão escritos como ISOWeek.GetWeek(...) e ISOWeek.GetYear(...)

Talvez faça sentido ter:
c# public DateTime ToDateTime(int year, int week, int day); public DateTime ToDateTime(int year, int week, DayOfWeek day); public DateTime ToDateTime(int year, int weekOfYear); public DateTime ToDateTime(int year, int dayOfYear);

Semana ISO geralmente usando dias de 1 a 7, enquanto DayOfWeek tem dias de domingo=0 a sábado = 6. você acha que isso pode criar confusão?

Não, de jeito nenhum. Já temos um enum representando o dia da semana. Seria uma pena se não o usássemos. Por que usaríamos um tipo menos específico aqui, mas um tipo mais específico ( DateTime ) em GetWeeksInYear , GetYearStart e GetYearEnd ?
Duvido que alguém se importe muito se Sunday representa 0 , 1 , 6 ou 7 . Eles só querem domingo, é isso. A API deve ser responsável por converter para a representação numérica correta.

Além disso, se usarmos DayOfWeek, você acha que aceitamos valores como (DayOfWeek) 7 ?

Eu diria que não. O que representaria? Estamos assumindo que eles querem domingo?

devemos apenas chamá-los GetWeek e GetYear ?

Sim, combinado 👍

O que acontece se você tiver um ano gregoriano que cruze 2 anos ISO? Aqui o exemplo,

Dom, 28 de dezembro de 2008 | 2008-W52-7
Seg 29 Dez 2008 | 2009-W01-1

Portanto, se você passar 2008 para nossas APIs, será ambíguo. É por isso que mencionei que as APIs precisam levar DateTime ou precisam levar o número do ano ISO e não o número gregoriano.

Ainda acho que você está confundindo isso com os outros métodos, que na verdade precisam do mês e da data.

Este seria o resultado se você passar 2008 para os diferentes métodos:

  • GetWeeksInYear : 52
  • GetYearStart : 2007-12-31 | 2008-W01-1
  • GetYearEnd : 2008-12-28 | 2008-W52-7

E só para completar, isto é o que 2009 lhe daria:

  • GetWeeksInYear : 53
  • GetYearStart : 2008-12-29 | 2009-W01-1
  • GetYearEnd : 2010-01-03 | 2009-W53-7

GetWeeksInYear sempre retornará o número de semanas no ano especificado. Não importa o mês e o dia. Este calendário ainda está no topo do calendário gregoriano.
GetYearStart e GetYearEnd retornarão a data de início e término gregoriana para o ano da semana ISO especificado.

Você pode dar um exemplo em que ter um mês e um dia realmente mudaria esses resultados?

Aqui está uma essência com minha implementação atual:

https://gist.github.com/khellang/53b98851b1d23eef97503ebb22612b3c

@khellang

Eu diria que não. O que representaria? Estamos assumindo que eles querem domingo?

sim. O cenário em minha mente é alguém recebendo uma data ISO de alguma fonte (que terá os dias de 1..7) e depois quer apenas chamar o framework com. se não tratarmos 7 como domingo, o chamador deve fazê-lo (dia % 7) antes de nos ligar.

Ainda acho que você está confundindo isso com os outros métodos, que na verdade precisam do mês e da data.

Acho que não estou confuso ou talvez ainda esteja confuso :-)
Pelo seu exemplo, parece que quando você mencionou 2008, você quis dizer que 2008 é o ano ISO e não o ano gregoriano. Isso é o que eu tentei dizer que as APIs levam o número do ano ISO. Olhe para o meu comentário anterior que eu disse or it has to take the ISO year number and not the Gregorian number. .

Por exemplo:

Ter alguém com DateTime e apenas passar DateTime.Year para as APIs seria a suposição errada. e eles precisarão fazer algo como:

```C#
DataHora dt = new DataHora(2008, 12, 29);
DateTime yearStart = ISOWeek.GetYearStart(ISOWeek.GetYear(dt)); // ISOWeek.GetYear(dt) retornará 2009 e não 2008.

This will return a different value than if you calling 

```C#
    DateTime yearStart = ISOWeek.GetYearStart(dt.Year);

Estou perdendo alguma coisa aqui? mas se isso corresponder ao que você está pensando, tudo bem se as APIs levarem apenas o número do ano e precisaremos esclarecer que esse número do ano é o número do ano ISO e não o número do ano gregoriano. Talvez possamos nomear o parâmetro como isoYear ou algo assim.

Eu não olhei seu código, mas vou dar uma olhada na primeira chance.

@iSazonov

eu acho que ter

C# public DateTime ToDateTime(int year, int week, DayOfWeek day);

é suficiente aqui. Não estou vendo que as sobrecargas sugeridas são necessárias.

mas se isso corresponder ao que você está pensando, tudo bem se as APIs levarem apenas o número do ano e precisaremos esclarecer que esse número do ano é o número do ano ISO e não o número do ano gregoriano.

Existe alguma diferença entre um "ano da semana ISO" e um "ano gregoriano"? Eu sei que eles podem começar e terminar em datas diferentes, mas 2009 no calendário gregoriano é 2009 no calendário semanal ISO, certo? Só é confuso quando você começa a envolver meses e dias.

Pelo menos ISOWeek.GetYearStart(ISOWeek.GetYear(dt)) pode ser bem composto.

Não tenho certeza se chamá-lo de year ou isoYear tornaria mais ou menos confuso 😂

Não tenho certeza se chamá-lo de ano ou isoano tornaria mais ou menos confuso

Se você acha que a confusão ainda existirá, podemos manter a proposta original de passar DateTime em vez do ano. não haveria confusão naquele momento.

A outra ideia pode ser ter uma sobrecarga para essas APIs, uma pega DateTime e a outra sobrecarga vai pegar o ano como você propôs. Ainda prefiro chamar o parâmetro como isoYear para essa sobrecarga.

Eu realmente me esforço para entender como isso o torna menos confuso. Isso força você a criar alguma entrada redundante, enquanto ainda passa o mesmo ano inteiro. Na minha opinião, isso não é apenas tão confuso, mas também mais trabalho sem nenhum benefício.

Vamos seguir em frente e confirmar a proposta de APIs que acho que todos nós concordamos agora:

C# namespace System.Globalization { public abstract class Calendar : ICloneable { public static class ISOWeek { public static int GetWeekOfYear(DateTime time); public static int GetYear(DateTime time); public static DateTime GetYearStart(int isoYear); public static DateTime GetYearEnd(int isoYear); public static int GetWeeksInYear(int isoYear); public static DateTime ToDateTime(int isoYear, int week, DayOfWeek day); } }

isso soa certo?

Deve ToDateTime() ser ToGregorianDateTime() ?

Como endereço "%G ano do número da semana ISO (consulte %V); normalmente útil apenas com %V"? Devemos adicionar a sobrecarga:
c# public static int GetYearOfWeek(int isoYear, int isoWeek);

isso soa certo?

Sim! Obrigado, @tarekgh ♥️

Desculpe, estive fora por alguns dias.

Eu não gosto muito do "DayOfWeek". Os calendários semanais ISO têm semanas equivalentes a meses de um calendário gregoriano tradicional, e o número do dia da semana é semelhante ao número do dia do mês em um calendário normal. Por isso, formata coisas como 2018-W12-7. Acontece que sabemos a qual "dia" esse 7 corresponde, no entanto, o formato ISO Week especifica os números dos dias. Claro, .Net tem uma classe DayOfWeek, mas isso para mim parece levar a uma alteração desnecessária dos valores.

Também não gosto muito da nomenclatura "isoYear". "Ano Iso" não é uma coisa. A ISO especifica a formatação de datas em um formato tradicional inequívoco de ano-mês-dia ou, opcionalmente, em formato de ano-semana-dia. "Ano" é um conceito ISO válido para ambos os sistemas. (E até sistemas adicionais). De fato, a ISO afirma especificamente que fornece orientação para números de anos gregorianos tradicionais, como exigir que sejam anos de 4 dígitos para evitar confusão Y2K. Por si só, "Iso Year" pode se aplicar a qualquer um, embora as pessoas às vezes encurtem "Iso Week Calendar Year", que é uma convenção enganosa.

O fato de essa classe ser a classe IsoWeek deve ser suficiente para determinar que um ano civil da semana ISO é entendido como "ano". Se IsoWeek ainda for muito ambíguo, sugiro "IsoWeekCalendar" para reduzir ainda mais a confusão. Se "iso" for necessário, então por que não "isoWeek" e "isoDay" também? Particularmente "semana" tem exatamente o mesmo qualificador de que esta é uma semana do Calendário da Semana Iso e não alguma outra semana.

@ShawnSteele Obrigado por entrar na conversa novamente!

Claro, .Net tem uma classe DayOfWeek, mas isso para mim parece levar a uma alteração desnecessária dos valores.

Acho que não devemos ficar muito presos aos valores. O enum fornece uma maneira de representar "dia da semana" e já é usado em todas as APIs de calendário/data/hora do .NET. Devemos pelo menos fornecer uma sobrecarga com ele, para que funcione perfeitamente com as outras APIs.

nomenclatura "isoYear". "Ano Iso" não é uma coisa. A ISO especifica a formatação de datas em um formato tradicional inequívoco de ano-mês-dia ou, opcionalmente, em formato de ano-semana-dia. "Ano" é um conceito ISO válido para ambos os sistemas. (E até sistemas adicionais). De fato, a ISO afirma especificamente que fornece orientação para números de anos gregorianos tradicionais, como exigir que sejam anos de 4 dígitos para evitar confusão Y2K. Por si só, "Iso Year" pode se aplicar a qualquer um, embora as pessoas às vezes encurtem "Iso Week Calendar Year", que é uma convenção enganosa.

O fato de essa classe ser a classe IsoWeek deve ser suficiente para determinar que um ano civil da semana ISO é entendido como "ano". Se IsoWeek ainda for muito ambíguo, sugiro "IsoWeekCalendar" para reduzir ainda mais a confusão. Se "iso" for necessário, então por que não "isoWeek" e "isoDay" também? Particularmente "semana" tem exatamente o mesmo qualificador de que esta é uma semana do Calendário da Semana Iso e não alguma outra semana.

Sim, por isso eu disse:

Existe alguma diferença entre um "ano da semana ISO" e um "ano gregoriano"? Eu sei que eles podem começar e terminar em datas diferentes, mas 2009 no calendário gregoriano é 2009 no calendário semanal ISO, certo? Só é confuso quando você começa a envolver meses e dias.

``` c#
public static int GetWeekOfYear(DateTime time);
public static int GetYear(DateTime time);

Would it make sense to add overloads that accept `DateTimeOffset` instead of `DateTime`, to make these methods easier to use for people who have to care about time zones? In other words:

```c#
public static int GetWeekOfYear(DateTime time);
public static int GetWeekOfYear(DateTimeOffset time);
public static int GetYear(DateTime time);
public static int GetYear(DateTimeOffset time);

Faria sentido adicionar sobrecargas que aceitam DateTimeOffset em vez de DateTime , para tornar esses métodos mais fáceis de usar para pessoas que precisam se preocupar com fusos horários?

O que as implementações fariam com as informações adicionais (o deslocamento UTC)?

@khellang

O que as implementações fariam com as informações adicionais (o deslocamento UTC)?

Eu acho que a mesma coisa que as sobrecargas DateTime fariam com DateTimeKind ou TimeOfDay : ignore.

Eu acho que a mesma coisa que as sobrecargas de DateTime fariam com DateTimeKind ou TimeOfDay : ignore-o.

Isso não se resume ao mesmo problema de ter que passar um DateTime se você estiver interessado apenas na propriedade Year ?

Idealmente, se o .NET tivesse um tipo Date puro, essas sobrecargas levariam apenas isso.

É fácil ir de DateTimeOffset para DateTime se isso é tudo que você precisa, não?

@khellang

É fácil ir de DateTimeOffset para DateTime se isso é tudo que você precisa, não?

Isto é. Eu só queria saber se tornar o trabalho com DateTimeOffset um pouco mais conveniente valeria a pena. Dessa forma, as pessoas não são desencorajadas a usar DateTimeOffset quando deveriam usá-lo.

Dessa forma, as pessoas não são desencorajadas a usar DateTimeOffset quando deveriam usá-lo.

Sou a favor de encorajar o uso de DateTimeOffset (quando você precisar), mas em termos de consistência e número de sobrecargas, não tenho certeza se vale a pena. De qualquer forma, não tenho uma opinião forte aqui. Tenho certeza de que os revisores da API terão alguns bons argumentos a favor ou contra.

Para o problema DateTimeOffset, não estou vendo que o ISOWeek está fazendo nada com fusos horários ou com o tempo em geral. trata principalmente da data e não da hora. então eu não acho que precisamos usar DateTimeOffset.

Para o problema DayOfWeek, gosto de usar o tipo explícito como DayOfWeek e ainda podemos permitir passar o valor 7 como domingo também. fazendo isso, não deve haver nenhum problema para alguém precisar nos ligar com valores de 1..7 (com conversão para DayOfWeek) ou alguém quiser nos ligar com DayOfWeek Sunday..Saturday. Eu não gosto de ter a sobrecarga que leva um número de dia da semana em vez de DayOfWeek.

Para o ano ISO, ainda vejo a diferença entre o ano gregoriano e o ano ISO. obviamente, o ano ISO pode começar em um momento diferente do ano gregoriano. O ano ISO pode ter a duração (número de dias ou número de semanas) diferente do ano gregoriano. É diferença suficiente para distinguir se estamos assumindo que o parâmetro de entrada é o ano gregoriano ou o ano ISO. assumir que o ano ISO é um ano gregoriano é uma suposição muito errada. Eu mencionei o exemplo anterior que pode fazer os chamadores se enganarem ao passar esse parâmetro para nossas APIs. minha posição aqui, ou devemos ser claros ao nomear o parâmetro como sugeri (ou melhor nome, se você tiver um) para indicar o número passado, indicar o ano ISO e não o número do ano gregoriano. Ou temos que deixar a API pegar DateTime que indica claramente que a API está pegando a data Gregoriana e podemos lidar com os casos extremos de acordo com os números do mês e do dia de acordo com o que obtemos do valor DateTime. Eu entendo o ponto @khellang que as pessoas não precisam construir o DateTime para apenas chamar nossas APIs, e eu concordo com ele. É por isso que aceitei deixar a API pegar o número do ano ISO e no futuro, se encontrarmos alguma necessidade de ter a API de sobrecarga leva DateTime, podemos adicioná-lo.

Ainda estou vendo que há a diferença entre o ano gregoriano e o ano ISO.

Por favor, é um ano gregoriano e um ano da semana ISO. Os anos ISO são ambíguos, sejam "gregorianos" ou "semana iso". Por exemplo, a ISO 8601 também especifica datas ordinais, por exemplo: 2018-117. Esse é um formato 'ISO' e, claramente, nesse formato ISO 2018 seria o ano ISO. Mas não é o mesmo que o ano da Semana ISO.

Se estou construindo um DateTime a partir de uma ISO Week Date, a única coisa que faz sentido é usar o ISO Week Year. Nesse caso, "iso" no nome do ano é redundante. Para que isso seja sensato, seria necessário:

public static DateTime ToDateTime(int isoWeekYear, int isoWeekWeek, DayOfWeek isoWeekDay);

Só que já dissemos que é uma aula "IsoWeek". então adicionar isso é bobagem.

Tenho dificuldade em ver um caso em que ToDateTime precise de um ano gregoriano normal, o que implica ainda que "ano" significando ano de formato de semana ISO é suficiente. Se eu estiver passando os outros 2 parâmetros usando o sistema ISO Week, não faria sentido incluir um ano gregoriano tradicional com os outros dados.

De qualquer forma, não me importo se as pessoas sentirem fortemente que ele precisa ser qualificado, apesar do nome da classe já implicar o domínio do formato IsoWeek. No entanto, se for mais qualificado, eu me oponho fortemente a perpetuar o uso indevido do termo absurdo "ano iso". a maioria dos formatos especificados pela ISO 8601 tem um ano que concorda com o ano gregoriano tradicional. Apenas o ano do formato de semana ISO é diferente.

@ShawnSteele qual é a sua sugestão aqui? basta nomeá-lo como "ano" e não isoYear"?

@tarekgh - Para DateTimeOffset, acho que é um item justo para consideração. As pessoas podem estar interessadas no formato do tipo ISO 2007-04-05T12:30-02:00, que inclui um fuso horário. Eu encorajaria fortemente o intercâmbio usando UTC, mas as datas/horas nem sempre são tão bem comportadas :(

@ShawnSteele qual é a sua sugestão aqui? basta nomeá-lo como "ano" e não isoYear"?

@tarekgh Sim, apenas "ano". A classe "IsoWeek" fornece contexto suficiente. Se as pessoas acharem que "IsoWeek" ainda é ambíguo, sugiro "IsoWeekFormat" ou algo que torne mais explícito que isso é tudo sobre o formato ISO 8601 Week.

Não há nenhum cenário em que faça sentido passar em um ano no formato de semana não iso junto com uma semana no formato de semana ISO e um dia no formato de semana iso.

Para DateTimeOffset, acho que é um item justo para consideração. As pessoas podem estar interessadas no formato do tipo ISO 2007-04-05T12:30-02:00, que inclui um fuso horário. Eu encorajaria fortemente o intercâmbio usando UTC, mas as datas/horas nem sempre são tão bem comportadas :(

Acho que não. atualmente estamos suportando DateTime.ToString("o") que fornece o formato ISO de acordo com DateTime (e DateTimeOffset). Não estou esperando ver o formato da semana Iso, incluindo as informações de fuso horário. o padrão suporta esse formato?

ok, com base na última discussão aqui está a proposta:

C# namespace System.Globalization { public abstract class Calendar : ICloneable { public static class ISOWeek { public static int GetWeekOfYear(DateTime time); public static int GetYear(DateTime time); public static DateTime GetYearStart(int year); public static DateTime GetYearEnd(int year); public static int GetWeeksInYear(int year); public static DateTime ToDateTime(int year, int week, DayOfWeek day); } }

isso seria razoável para todos vocês?

Por que a API proposta não inclui um dia da semana?

public static int GetDayOfWeek(DateTime time);

Se eu quiser formatar uma data no formato de semana ISO, esta classe fornece a parte do ano do formato de semana ISO "2018" e o número da semana "17", mas não há método para retornar o dia da semana "7" para Este Domingo.

Uma analogia seria como uma classe de informação de data gregoriana que fornecesse o ano, o mês, mas não a data (dia do mês).

Eu entendo totalmente que isso é muito semelhante ao DateTime.DayOfWeek - no entanto, o dia da semana ISO é deslocado da enumeração e é um número, não uma enumeração. O código é "direto", mas sempre exigiria munging, algo como

int isoWeekDay = DateTime.DayOfWeek == 0 ? 7 : (int)DateTime.DayOfWeek;

o que parece muito desajeitado, especialmente se a classe IsoWeek já estiver lá.

Acho que não. atualmente estamos suportando DateTime.ToString("o") que fornece o formato ISO de acordo com DateTime (e DateTimeOffset).

@tarekgh - sim, o padrão suporta esse formato. https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations

"Os formatos básico ou estendido podem ser usados, mas a data e a hora devem usar o mesmo formato. A expressão de data pode ser calendário, semana ou ordinal e deve usar uma representação completa."

Por que a API proposta não inclui um dia da semana?

O calendário gregoriano já tem isso. Eu realmente não estou vendo por que precisamos fazer isso? como mencionei antes, podemos considerar o fornecimento de opções de formatação separadamente desta proposta. então não há necessidade de fornecer API como o que você está propondo. as pessoas ainda podem converter o domingo para 7 se precisarem. Seria um exagero fornecer essa API para fazer isso.

sim, o padrão suporta esse formato. https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations

Eu não estou interpretando o parágrafo que você está falando da mesma forma. existe uma diferença entre representar a data e formatá-la. Estou vendo que a formatação de data ISO sempre usa ano, mês e dias (além de informações de horário e fuso horário), mas não estou vendo em nenhum lugar onde você possa usar um número de semana neste formato ISO. https://www.iso.org/iso-8601-date-and-time-format.html

ISO 8601 tackles this uncertainty by setting out an internationally agreed way to represent dates:

YYYY-MM-DD

Você me confundiu por "representar a data" versus "formatá-la". Todas as datas semanais ISO são representáveis ​​por DateTimes e não precisam dessa classe. Os Formatos de Semana ISO são principalmente uma convenção para formatar datas Gregorianas de uma maneira conveniente para algumas empresas.

Os contextos que estou acostumado a ver essas datas estão em uma escala de tempo "semanas para um projeto" ou "dia", no entanto 2018-W17-05T10:00:00+02:00 (e 2018-117T10:00:00+02: 00) são certamente permitidos pela norma. Claro, ele pode ser representado no formato YMD, no entanto, a ISO 8601 não exige o formulário YMD para a parte da data e permite que os usuários do padrão escolham como desejam representar a parte da data de um formato Data+Hora completo. (Os usuários também podem optar por usar UTC ou outras representações de hora também).

Claro, muitos RFCs e outros padrões especificam o formato 2018-04-27 para consistência e portabilidade, no entanto, o ISO 8601 não é tão restrito.

no entanto, a ISO 8601 não é tão restrita.

você poderia me enviar o link do padrão ISO permitir isso (quero dizer, permitir o formato como 2018-W17-05T10:00:00+02:00)? Agradeço sua ajuda aqui.

Além disso, estou interessado se você puder escrever algum exemplo de código como espera que as pessoas escrevam código para usar nossas APIs propostas com DateTimeOffset? Quero dizer, quando DateTimeOffset seria mais beneficiário do que DateTime? ou em outras palavras, quando nossas novas APIs propostas se preocuparão com o tempo?

Eu não acho que DateTimeOffset precisa ser abordado agora. Poderíamos usar DateTime e ver se as pessoas clamam por um DateTimeOffset. Se sim, pode ser adicionado mais tarde. Eu não acho que deve bloquear este trabalho.

Estou bem com a proposta que você postou por último.

Obrigado @ShawnSteele

Vou atualizar a proposta no topo com o seguinte:

C# namespace System.Globalization { public abstract class Calendar : ICloneable { public static class ISOWeek { public static int GetWeekOfYear(DateTime time); public static int GetYear(DateTime time); public static DateTime GetYearStart(int year); public static DateTime GetYearEnd(int year); public static int GetWeeksInYear(int year); public static DateTime ToDateTime(int year, int week, DayOfWeek day); } }

E vou remover a seção de design alternativo, pois o que temos aqui é uma proposta muito melhor de qualquer maneira. Obrigado a todos pelo seu valioso feedback.

Isso é perfeito no que me diz respeito, @tarekgh. Obrigado!

Parece bom. ISO não deveria estar em letras maiúsculas, mas já temos APIs de globalização com todas as letras maiúsculas, então esse navio já partiu.

Aninhar esse tipo no calendário força todos a usar nomes qualificados muito longos (por exemplo Calendar.ISOWeek.GetWeekOfYear() vs apenas ISOWeek.GetWeekOfYear() ), portanto, promover ISOWeek para um tipo de nível superior parece melhor, especialmente porque ajuda na descoberta.

namespace System.Globalization
{
    public static class ISOWeek
    {
        public static int GetWeekOfYear(DateTime time);
        public static int GetYear(DateTime time);
        public static DateTime GetYearStart(int year);
        public static DateTime GetYearEnd(int year);
        public static int GetWeeksInYear(int year);
        public static DateTime ToDateTime(int year, int week, DayOfWeek day);
    }
}

@khellang Enviei a você um convite de colaborador para que possamos atribuir o problema a você (limitação do GH). Faça um ping para mim assim que aceitar (atribuindo a mim mesmo temporariamente).
Dica profissional: mude o repositório para "Não assistindo" para evitar mais de 500 notificações diariamente (você será inscrito automaticamente em todas as notificações como colaborador).

Feito! Eu acompanho o repo há anos de qualquer maneira 😉

@terrajobst este problema deve ser marcado como aprovado pela API?

Sim, isso foi aprovado (marcando como tal). O computador do @terrajobst estava muito lento para fazer a mudança :(

Apenas uma pergunta rápida: esse tipo deve ser adicionado ao System.Private.CoreLib (no coreclr) e aguardar o código sincronizar com o corefx e o coret? E então adicionar encaminhamento de tipo e testes em System.Globalization?

Apenas uma pergunta rápida: esse tipo deve ser adicionado ao System.Private.CoreLib (no coreclr) e aguardar o código sincronizar com o corefx e o coret? E então adicionar encaminhamento de tipo e testes em System.Globalization?

Sim, adicione o código ao repositório coreclr e me envie uma CC no PR. Obrigado.

Muito Obrigado!

@tarekgh O aprimoramento está no 2.1.1?

É atribuído ao marco 3.0, então não pense assim 🤔

Correto. 2.1.1 está atendendo. Não adicionamos recursos ou correções não críticas em branches de serviço, que os desestabilizariam e os tornariam basicamente outro branch master.

Obrigado! Vejo marco 3.0 em PRs.

Eu costumo fazer varreduras de marcos incorretos (como Futuro) 1x-2x a cada semana para ambos os problemas e PRs.
Estou um pouco atrasado devido a alguns high-pris no meu prato, desculpe. Vou pegar assim que puder.

ISOWeek não é uma violação das diretrizes de nomenclatura do framework?

@paulomorgado Leia https://github.com/dotnet/corefx/issues/28933#issuecomment -392873426 alguns comentários acima.

Não adicionamos recursos ou correções não críticas em branches de serviço, que os desestabilizariam e os tornariam basicamente outro branch master.

@karelz Mas isso será lançado com 2.2?

Desculpe @khellang , eu como no phonw.

Mas será que este navio com 2.2?

Infelizmente não. 2.2 é a versão tática desativada da ramificação da versão/2.1 no repositório CoreFX (serviço 2.1) - nota: Essa é uma decisão específica do repositório, não necessariamente refletida em outros repositórios (ASP.NET, CLI, etc.). A ramificação mestre flui para o .NET Core 3.0 no repositório CoreFX.

Tarde para a festa: houve (não consigo encontrar) uma discussão considerando fazer um tipo dedicado (struct) para um número de semana? - IsoWeek / IsoWeekNumber / WeekNumber contendo as propriedades Year e Week .
IMHO parece mais conciso do que precisar chamar dois métodos para obter dois números que representam uma única coisa.
Não tenho certeza de como outras pessoas usam os números da semana, mas eu costumava precisar da semana e do ano juntos na maioria dos casos.

houve uma discussão sobre a possibilidade de fazer um tipo dedicado para um número de semana?

Não. A proposta sempre foi sobre métodos para obter as informações que você precisa em diferentes situações. Criar um tipo que envolva esses números seria uma proposta diferente.

IMHO parece mais conciso do que precisar chamar dois métodos para obter dois números que representam uma única coisa.

A quais chamadas você se refere? Quais informações você tem e em quais informações você está interessado?

Se você tiver "uma única coisa" composta por dois números, faz muito sentido dividir esses métodos. Escrever uma estrutura de encapsulamento e compor esses métodos posteriormente é trivial.

Também um pouco atrasado para a festa, mas por que os valores de retorno são int ? Saiba que 2016-01-02 caiu na semana 2015.53 e 2019-12-31 estará na semana 2020.01

Ainda não consigo usar algo assim:
``` c#
int semana = ISOWeek.GetWeekOfYear(new DateTime(2016, 1, 2));

I do need to check something like every time I need to know a week:
```c#
var d = new DateTime(2016, 1, 2)
int week = ISOWeek.GetWeekOfYear(d);
int year = d.Year;
if (d.Month == 1 && week >= 52)
    year--;
if (d.Month == 12 && week == 1)
   year++;

Por que não devolver uma Tupla?
c# public static (int year, int week) GetWeekOfYear(DateTime date);

Por que não devolver uma Tupla?

@ffes Se você tem var d = new DateTime(2016, 1, 2) , você deve ser capaz de fazer

var year = ISOWeek.GetYear(d);
var week = ISOWeek.GetWeekOfYear(d);

Se você quiser rolar isso em um único método retornando uma tupla, isso deve ser muito fácil de fazer.

Eu perdi a existência de GetYear() . Desculpem o barulho :aliviado:

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

nalywa picture nalywa  ·  3Comentários

jchannon picture jchannon  ·  3Comentários

v0l picture v0l  ·  3Comentários

GitAntoinee picture GitAntoinee  ·  3Comentários

aggieben picture aggieben  ·  3Comentários