Finalización de la semana laboral

8

Trabajo un estándar de nueve a cinco. De lunes a viernes. Tomo media hora para el almuerzo de 12:30 a 13:00.

Escríbame un programa que, cuando se ejecute, calcule el porcentaje de la semana laboral que he completado en el momento actual.

Reglas

  • Solo cuente el tiempo que realmente pasó trabajando. Soy puntual y no trabajo durante el almuerzo.
  • Sin entrada. Puede obtener información como la hora / fecha actual, sin embargo, es conveniente.
  • La semana laboral se considera completa desde el final del día del viernes hasta la medianoche entre el domingo y el lunes.
  • La zona horaria es la zona horaria local.
  • La salida debe ser un número decimal, por ejemplo, 66.25498, símbolo de porcentaje opcional.
  • El programa debe ser razonablemente a prueba de futuro. Debería poder hacer frente a los años bisiestos.
  • La resolución de salida debe ser un segundo o mejor. Me gusta ver hervir la tetera.
  • Código de golf. El código más corto gana.
skeevey
fuente
1
¿Cuál es tu zona horaria? Sistema local? ¿GMT? Ah, ¿y es medianoche entre el sábado y el domingo o el domingo y el lunes?
Ilmari Karonen
Actualicé las reglas. Hora local, y el domingo / lunes a medianoche.
skeevey
¿Está ganando salarios durante el almuerzo?
DavidC
¿No creo que eso haga la diferencia?
skeevey
si estás en el almuerzo, no estás trabajando, por lo tanto, supongo que en una semana laboral de 37.5 horas
SeanC

Respuestas:

4

Q, 111 102

0|100*("i"$(27000000*((.z.d)mod 7)-2)+{0|((17:00:00&x)-09:00:00)-0|00:30:00&x-12:30:00}.z.t)%135000000
tmartin
fuente
5

Pitón 3, 132

from datetime import*
t=datetime.now().timetuple()
m=max(0,t[3]*2+t[4]/30-18)
print(20*min(5,(t[6]+min(15,m-min(8,max(7,m))+7)/15)))

La resolución es de un minuto, o 2/45 de un porcentaje. Eso es más que suficiente OMI.

Fraxtil
fuente
5

Excel, 132 , 129 , 123 , 119 , 117

pegar en A2: A4

=NOW()
=A2-INT(A2)-.375
=(WEEKDAY(A2,3)*7.5+IF(A3<0,0,IF(A3>TIME(8,0,0),7.5,(A3-IF(A3>.1875,TIME(0,30,0),0))*24)))/37.5

formatee la celda A4 como% para obtener el formato correcto

Almuerzo remunerado de 40 horas semanales:

88 , 81

=NOW()
=A1-INT(A1)-.375
=(WEEKDAY(A1,3)*8+IF(A2<0,0,IF(A2>TIME(8,0,0),8,A2*24)))/40
SeanC
fuente
El primero no parece funcionar cuando NOW()es un tiempo después de las 5PM.
Gaffi
augh - a * 24 en la posición incorrecta .....
SeanC
:-) Por cierto, buen trabajo superándome en mi enfoque VBA usando fórmulas en su lugar. Ahora estoy jugando ... ¡Su actualización agregó un char ( 0) que no es necesario!
Gaffi
mi excusa es que no he estado en el trabajo después de las 5:00 durante bastante tiempo: D
SeanC
2

Perl, 124 caracteres

OK, primera solución simple para establecer el par:

say(($p=((($s,$m,$h,@t)=localtime)[6]+6)%7*20+(($h+=$m/60+$s/3600-9)<0?0:$h<3.5?$h:$h<4?3.5:$h<8?$h-.5:7.5)*8/3)<100?$p:100)

Ejecute con perl -M5.010para habilitar la función Perl 5.10+ say. La resolución es un segundo; Si la resolución de un minuto es aceptable, la +$s/3600parte se puede eliminar para una longitud total de 116 caracteres .

Esta solución se utiliza localtimepara obtener el día de la semana y la hora del día, por lo que debería funcionar independientemente de los cambios de año, los días bisiestos o cualquier otra peculiaridad del calendario, al menos mientras el ciclo semanal de siete días no cambie. Los cambios en el horario de verano durante la jornada laboral lo confundirían un poco, pero básicamente nunca suceden de todos modos, presumiblemente precisamente porque eso generaría demasiada confusión.

(Para mayor comodidad, tenga en cuenta que localtimeacepta una marca de tiempo Unix como argumento opcional).

Ilmari Karonen
fuente
2

Mathematica 169 168 212 214 211 218 210 190 caracteres

De largo aliento, según los estándares de golf de código.

Lo siguiente tiene en cuenta las semanas laborales que cruzan los límites de mes o año, así como los años bisiestos. Calcula el tiempo trabajado según horas y minutos.

No podía pensar en una forma de evitar explicar los días de la semana. Mathematica devuelve el día de la semana como una cadena de 3 caracteres, que debe convertirse en un número.

h = Plus @@ {#1, #2/60, #3/3600} & @@ Take[DateList[], -3]; 100*Min[37.5, (StringTake[DateString[], 3] /. {"Mon" -> 0, "Tue" -> 1, "Wed" -> 2 , "Thu" -> 3, "Fri" -> 4, _ -> 5})*7.5 + Which[h < 12.5, Max[0, h - 9], h < 13, 4, True, 4 + Min[h - 13, 4]]]/37.5

De golf

(* d returns {year, mo, day, h, m, s}   *)
d = DateList[]

(* finished Days: hours worked *)
f = (StringTake[DateString[],  3] /. {"Mon" -> 0, "Tue" -> 1, "Wed" -> 2 , "Thu" -> 3, "Fri" -> 4, _ -> 5})*7.5

(* time of day in hours *)
h = Plus @@ {#1, #2/60} & @@ Take[d, -3]

(* today: hours Worked. It also computes hours for Sat and Sunday but does not use 
them in the final tabulation, which has a maximum of 37.5. *)
t = Which[h < 12.5, Max[0, h - 9], h < 13, 4, _, 4 + Min[h - 13, 4]]

(* hours Worked in week *)
tot = Min[37.5, f + t]

(* % of working week completed *)
100*tot/37.5

semana de trabajo

DavidC
fuente
2

VBA 141

Formateado para ejecutarse desde la ventana inmediata. ¡Gracias a Sean Cheshire por señalar una mejora de 10 caracteres!

n=(Now-Int(Now))*24:a=(Weekday(Now,3)*7.5+IIf(n>17,7.5,IIf(n>9,IIf(n<12.5,n,IIf‌​(n>13,n-.5,n))-9,0)))/37.5:MsgBox Format(IIf(a>1,1,a),".0%")
Gaffi
fuente
use n = n * 24, y se puede reducir más. mi pelea con esto produjo esto: n=(Now-Int(Now))*24:a=(Weekday(Now,3)*7.5+IIf(n>17,7.5,IIf(n>9,IIf(n<12.5,n,IIf(n>13,n-.5,n))-9,0)))/37.5:MsgBox Format(IIf(a>1,1,a),".0%")@ 139
SeanC
@SeanCheshire Excelente punto! Mi método tenía algo de sintaxis sobrante de una versión anterior que usaba n, por lo que no se pudo modificar.
Gaffi
1

R, 115 caracteres

---------1---------2---------3---------4---------5---------6---------7---------8---------9---------0---------1---------2
T=as.POSIXlt(Sys.time()-86400);z=T$h+T$mi/60-9;D=function(x,M)min(M,max(0,x));D(((D(z,8)-D(z-3.5,.5))/7.5+T$w)/5,1)

Aquí hay una simulación de una semana:

week.frac <- function(t) {
   T <- as.POSIXlt(t-86400)
   z <- T$h+T$mi/60-9
   D <- function(x,M)min(M,max(0,x))
   D(((D(z,8)-D(z-3.5,.5))/7.5+T$w)/5,1)
}

time <- seq(from = as.POSIXlt(as.Date("2012-08-20")),
            to   = as.POSIXlt(as.Date("2012-08-27")),
            by   = "min")
week.completion <- sapply(time, week.frac)
plot(time, week.completion, type = "l")

semana completada para la semana actual

flodel
fuente
1

Rubí, 191 116,115 113

La lógica es robada de la solución Fraxtils Python .

t=Time.now
d=t.wday
m=[0,t.hour*2+t.min/3e1-18].max
p d<1?100:20*[5,(d-1+[15,m-[8,[7,m].max].min+7].min/15)].min

Si desea probar el código con la prueba unitaria, necesita esta solución de 143 caracteres:

class Time  
def r
m=[0,hour*2+min/3e1-18].max
d=wday
d<1?100:20*[5,(d-1+[15,m-[8,[7,m].max].min+7].min/15)].min
end    
end
p Time.now.r

No es el código más corto y eficiente, pero con una prueba de unidad;)

Los 191 caracteres incluyen las nuevas líneas (podría convertirlo en una línea, simplemente reemplace cada nueva línea con a ;).

class Time
def r
i=0
d{|t|i+=t.w}
i/1350.0
end
def d
t=dup
yield t-=1 until t.strftime('%w%T')=='109:00:00'
end
def w
h=hour
wday<1||wday>5||h<9||h>16||h==12&&min>29?0:1
end
end
p Time.now.r

Y el código de prueba:

require 'test/unit'
class MyTest < Test::Unit::TestCase
  def test_mo
    assert_equal( 20, Time.new(2012,8,13,20).r) #monday
  end
  def test_tue
    assert_equal( 40, Time.new(2012,8,14,20).r) #tuesday
  end
  def test_wed_morning
    assert_equal( 40, Time.new(2012,8,15,7).r)
  end
  def test_wed
    assert_equal( 60, Time.new(2012,8,15,20).r)
  end
  def test_thu
    assert_equal( 80, Time.new(2012,8,16,20).r)
  end
  def test_fri
    assert_equal(100, Time.new(2012,8,17,20).r)
  end
  def test_sat
    assert_equal(100, Time.new(2012,8,18,20).r)
  end
  def test_sun
    assert_equal(100, Time.new(2012,8,19,20).r)
  end
  def test_middle
    assert_equal(50, Time.new(2012,8,15,13,15).r)
  end
end
Knut
fuente
0

Python 2 130 caracteres

from datetime import*
t=datetime.now().timetuple();
m=min
a=max
n=t[3]+t[4]/60.0
print m(17,a(9,n))-9-(a(0,m(.5,n-12.5)))+7.5*m(t[6],4)

El tercer intento es una salsa débil pero creo que he entendido bien la lógica.

chucksmash
fuente
1
Esto no funciona A simple vista de la salida, no hay largos períodos de tiempo en los que el porcentaje permanezca igual, lo que debería ser el caso entre las 5:00 p.m. de cada día y las 9:00 a.m. del día siguiente, así como cada 12:30 -1: 00 PM intervalo. También genera números negativos y números superiores a 100 a veces.
Fraxtil
Oh, lástima de mí. Estás absolutamente en lo correcto. Mulligan
chucksmash
@Fraxtil Creo que te he superado por un pelo
chucksmash
Esto parece tener un rango de 0 a 37.5. Sin embargo, se detiene durante los intervalos apropiados.
Fraxtil
Oh, lo tenía configurado para imprimir el número de horas para la depuración. Olvidé cambiarlo a% por respuesta. Supongo que no podré hacer eso en 2 personajes, así que supongo que me tienes después de todo
Chucksmash